def split_parts(pool, preproces_dir, g_conf): target_dir = g_conf["target_dir"] original_dir = g_conf["original_dir"] error_dir = g_conf["error_dir"] start_y = g_conf["start_y"] collectData = g_conf["collectData"] splitMode = g_conf["splitMode"] preproces_files = get_image_paths_from_dir(preproces_dir, 'png') futures = [] for preproces_path in preproces_files: out_dir, dir_name = get_out_dir_name(preproces_path, target_dir) futures.append( pool.apply_async(split_parts_for_image, (start_y, preproces_path, out_dir, dir_name, original_dir, collectData, splitMode))) for future in futures: name, success = future.get() copyName = get_jpeg_name_for_png(get_specified_dir(original_dir, name)) if success: print("分解成功: ", copyName) else: distName = get_specified_dir(error_dir, get_jpeg_name_for_png(name)) copy_move_file(copyName, distName) print("分解失败: ", copyName)
def find(img, path, target): img_small = resize_to_resolution(img, 1024) small_h, w = img_small.shape[:2] im = cv2.GaussianBlur(img_small, (1, 1), 0) gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray, *(20, 30)) edges = cv2.dilate(edges, None) edges = cv2.erode(edges, None) (_, thresh) = cv2.threshold(edges, 127, 255, cv2.THRESH_BINARY) cimg, cnts, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # cv2.imshow("1",cimg) # cv2.waitKey(0) valid = [] for cnt in cnts: x, y, w, h = cv2.boundingRect(cnt) if h == small_h: valid.append(x) if len(valid) >= 2: # print('检索出更多的图',path) new_file_name = get_specified_dir(target, get_file_name(path)) cv2.imwrite(new_file_name, img_small) return img_small
def preprocessImage(pool, image_files, g_conf): futures = [] temp_dir = g_conf["temp_dir"] start_y = g_conf["start_y"] end_y = g_conf["end_y"] resize = g_conf["resize"] preproces_dir = create_specified_dir(temp_dir, "1_preprocess") for path in image_files: futures.append( pool.apply_async(preprocess_image, (path, temp_dir, start_y, end_y, resize))) imageObjs = [] for future in futures: img, path = future.get() imageObjs.append(img) new_file_name = get_specified_dir(preproces_dir, get_png_name_for_jpeg(path)) cv2.imwrite(new_file_name, img) return preproces_dir
def get_mask_file_name(img_file): data_dir = get_data_dir(img_file) masks_dir = get_specified_dir(data_dir, "2_masks") png_name = get_png_name_for_jpeg(img_file) return os.path.join(masks_dir, png_name)
def legao_main(original_dir="", target_dir="", interval="", error_dir="", start_y="", collectData="", splitMode="", resize="", end_y=""): if original_dir == "": print("必须传递原图目录 original_dir") return if target_dir == "": print("必须传递保存目录 target_dir") return if start_y == "": print("必须设置截图的Y轴上部距离(px) start_y") return if end_y == "": print("必须设置截图的Y轴下部距离(px) end_y") return # 临时保存目录 temp_dir = get_specified_dir(original_dir, "temp") error_dir = error_dir or get_specified_dir(original_dir, "error") # 根目录处理 asscess_dir(target_dir) asscess_dir(temp_dir) asscess_dir(error_dir) original_image_total_files = get_image_paths_from_dir(original_dir, 'jpg') g_conf = { "collectData": collectData, "splitMode": splitMode, "interval": interval, "resize": resize, "start_y": start_y, "end_y": end_y, "original_dir": original_dir, "target_dir": target_dir, "temp_dir": temp_dir, "error_dir": error_dir } # 赋全局值 for prop in g_conf: if not g_conf[prop]: g_conf[prop] = config[prop] modeName = "全部保留" if splitMode == "full": modeName = "仅保留完整的零件" message = [ ["原图目录: ", original_dir], ["临时目录: ", temp_dir], ["错误目录: ", error_dir], ["完成目录: ", target_dir], ["原图截取从Y: ", start_y], ["原图截止至Y: ", end_y], ["分解量: ", interval], ["切割模式: ", modeName], ] for name in message: print(name[0], name[1], sep="") #开始任务 exec_process_image(0, original_image_total_files, g_conf)
def split_parts_for_image(start_y, preproces_path, out_dir, dir_name, original_dir, collectData, splitMode): try: # 第三步图片 segmented_img = cv2.imread(get_seg_file_name(preproces_path)) # 原始图 original_img = cv2.imread( get_specified_dir(original_dir, dir_name + ".jpg")) # 原图宽度 original_width = original_img.shape[1] original_resize = original_width / 1000 width = segmented_img.shape[1] height = segmented_img.shape[0] #定义区域 min_area = 50 max_area = width * height # BGR=>灰度图 mask = cv2.cvtColor((segmented_img != 0).astype(np.uint8), cv2.COLOR_BGR2GRAY) # 部件图 partImages = [] # 边缘部件 part_remove_left = 0 part_remove_right = 0 while True: # 将mask转化为1维数组 # 返回数组mask中值不为零的元素的下标, nz = np.nonzero(mask.flatten())[0].flatten() if len(nz) == 0: break nz_i = 0 found_mask = None found_image = None while True: index = nz[nz_i] seed_x = index % width # 向下取整 seed_y = index // width ff_mask = np.zeros((height + 2, width + 2), dtype=np.uint8) area, _, __, rect = cv2.floodFill(mask, ff_mask, (seed_x, seed_y), 255, flags=cv2.FLOODFILL_MASK_ONLY | cv2.FLOODFILL_FIXED_RANGE) x = rect[0] y = rect[1] w = rect[2] h = rect[3] # slicing into found rect roi_mask = ff_mask[y + 1:y + 1 + h, x + 1:x + 1 + w] found = False if min_area < area < max_area: found_mask = roi_mask newX = x * 4 newY = (y * 4) + start_y newW = w * 4 newH = h * 4 # 边界模式,跳出循环 if splitMode == "full": if newX <= 0: found_mask = None part_remove_left += 1 if newW + newX >= original_width: found_mask = None part_remove_right += 1 startX = newX - 30 endX = newX + newW + 30 startY = newY - 30 endY = newY + newH + 30 found_image = original_img[startY:endY, startX:endX].copy() found = True # clearing found component in the mask mask[y:y + h, x:x + w][roi_mask != 0] = 0 if found: break nz_i += 1 if nz_i >= len(nz): break if found_mask is not None: partImages.append(found_image) # 如果有多个零件,创建目录保存 # hasmorepart = len(partImages) > 1 # if hasmorepart: out_dir = get_specified_dir(out_dir, dir_name) if os.path.exists(out_dir): clear_dir(out_dir) else: create_dir(out_dir) # 分割信息 if part_remove_left or part_remove_right: fl = open(out_dir + "/data.json", 'w') r_data = { "left_remove": part_remove_left, "right_remove": part_remove_right } fl.write(json.dumps(r_data, ensure_ascii=False, indent=2)) fl.close() # 输出第二部分 part_index = 0 for part in partImages: title = os.path.splitext(os.path.split(preproces_path)[1])[0] file_name = os.path.join("", "%s_%02d.png" % (title, part_index)) # if hasmorepart: out_file = os.path.join(out_dir, "%s_%02d.png" % (title, part_index)) # else: # out_file = os.path.join(out_dir, "%s.png" % (title)) cv2.imwrite(out_file, part) # 支持数据采集 if collectData: color_thief = ColorThief(out_file) dominant_color = color_thief.get_color(quality=1) h, w = part.shape[:2] datas = { "name": file_name, "w": w, "h": h, "area": w * h, "rgb": dominant_color } filePath = out_dir + "/data.json" if (os.path.exists(filePath)): fl = open(filePath, 'a') else: fl = open(filePath, 'w') fl.write(json.dumps(datas, ensure_ascii=False, indent=2)) fl.close() part_index += 1 return dir_name + ".png", True except Exception as _: return dir_name + ".png", False
def get_out_dir_name(img_file, target_dir): out_dir = get_specified_dir(target_dir, "") dir_name = os.path.splitext(os.path.split(img_file)[1])[0] return out_dir, dir_name
def get_seg_file_name(img_file): data_dir = get_data_dir(img_file) seg_dir = get_specified_dir(data_dir, "3_segmentation") png_name = get_png_name_for_jpeg(img_file) return os.path.join(seg_dir, png_name)
def split_parts_for_image(start_y, preproces_path, out_dir, dir_name, original_dir, collectData, splitMode): try: # 第三步图片 segmented_img = cv2.imread(get_seg_file_name(preproces_path)) # 原始图 original_img = cv2.imread( get_specified_dir(original_dir, dir_name + ".jpg")) # 原图宽度 original_width = original_img.shape[1] original_resize = original_width / 1000 width = segmented_img.shape[1] height = segmented_img.shape[0] #定义区域 min_area = 50 max_area = width * height # BGR=>灰度图 mask = cv2.cvtColor((segmented_img != 0).astype(np.uint8), cv2.COLOR_BGR2GRAY) # 部件图 partImages = [] # 边缘部件 part_remove_left = 0 part_remove_right = 0 #参考点标签的坐标合计 labelPoint = [] newimage = original_img.copy() while True: # 将mask转化为1维数组 # 返回数组mask中值不为零的元素的下标, nz = np.nonzero(mask.flatten())[0].flatten() if len(nz) == 0: break nz_i = 0 found_mask = None found_image = None while True: index = nz[nz_i] seed_x = index % width # 向下取整 seed_y = index // width ff_mask = np.zeros((height + 2, width + 2), dtype=np.uint8) area, _, __, rect = cv2.floodFill(mask, ff_mask, (seed_x, seed_y), 255, flags=cv2.FLOODFILL_MASK_ONLY | cv2.FLOODFILL_FIXED_RANGE) x = rect[0] y = rect[1] w = rect[2] h = rect[3] # slicing into found rect roi_mask = ff_mask[y + 1:y + 1 + h, x + 1:x + 1 + w] found = False # 找指定区域的内容 if min_area < area < max_area: found_mask = roi_mask newX = x * 4 newY = (y * 4) + start_y newW = w * 4 newH = h * 4 # 边界模式,跳出循环 if splitMode == "full": if newX <= 0: found_mask = None part_remove_left += 1 if newW + newX >= original_width: found_mask = None part_remove_right += 1 # 扩散30px截取 startX = newX - 30 endX = newX + newW + 30 startY = newY - 30 endY = newY + newH + 30 found_image = original_img[startY:endY, startX:endX].copy() found = True out_file = os.path.join(out_dir, "%s.png" % (newX)) cv2.imwrite(out_file, found_image) # 数字下标 if newW < 400 and newH > 100 and newH < 200 and newY > 1800: out_file = os.path.join(out_dir, "%s.png" % (newX)) cv2.imwrite(out_file, found_image) pox = preproces_line( out_file, os.path.join(out_dir, "%s.line.png" % (newX))) left_top_x, left_top_y = pox[0] left_bottom_x, left_bottom_y = pox[1] # 计算在图中真实坐标 left_top_x += startX left_top_y += startY left_bottom_x += startX left_bottom_y += startY # 目标的X坐标 targetX = getXValue((left_bottom_x, left_bottom_y), (left_top_x, left_top_y), 1050) labelPoint.append( [left_bottom_x, left_bottom_y, int(targetX), 1050]) cv2.line(newimage, (left_bottom_x, left_bottom_y), (int(targetX), 1050), (255, 255, 0), 10) found_mask = None # 找到其余的元素 if found_mask is not None: centerX = newX + newW / 2 centerY = newY + newH / 2 partImages.append( [int(centerX), int(centerY), found_image]) out_file = os.path.join(out_dir, "%s.png" % (newX)) cv2.imwrite(out_file, found_image) # clearing found component in the mask mask[y:y + h, x:x + w][roi_mask != 0] = 0 if found: break nz_i += 1 if nz_i >= len(nz): break # 获取交叉点坐标 crosslineDistance(newimage, partImages, labelPoint) # 输出线图 cv2.imwrite(os.path.join(out_dir, "%s.png" % (dir_name)), newimage) return dir_name + ".png", True except Exception as _: return dir_name + ".png", False