def imgHandle(img, feature): resultArr = [] # 灰度 grayImg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值 ret, th = cv2.threshold( grayImg, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # 膨胀 kernel = np.ones((3, 3), np.uint8) dilation = cv2.dilate(th.copy(), kernel) # 膨胀 # cv_show('dilation', dilation) # 轮廓 refCnts, hierarchy = cv2.findContours( dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) refCnts = utils.sort_contours( refCnts, method="left-to-right")[0] # 排序从左到右,从上到下 for(i, c) in enumerate(refCnts): # 计算外接矩形并且resize成合适大小 (x, y, w, h) = cv2.boundingRect(c) if w > 20 and w < 26 and h > 18 and h < 26: cv2.rectangle(th, (x, y), (x + w, y + h), (0, 0, 0), 1) # cv_show('img', th[y:y+h, x:x+w]) resultArr.append(discriminate(th[y:y+h, x:x+w], feature)) # cv_show('img', th) # 分割 # 识别方向 # 返回结果 return resultArr
def encontraTabelasAlunos(img, linhas): #Procura todos os contornos externos da imagem com as linhas contours = cv2.findContours(linhas, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0] contours = utils.sort_contours(contours, method="top-to-bottom")[0] if len(contours) > 0: todosContornos = [] todosContornosLinhas = [] roiAlunos = [] roiAlunosLinhas = [] for c in contours: perimetro = cv2.arcLength(c, True) area = cv2.contourArea(c) if (perimetro > 1000 and area > 50000): (x, y, w, h) = cv2.boundingRect(c) roi = img[y:y + h, x:x + w] todosContornos.append(roi) todosContornosLinhas.append((x, y, w, h)) if len(todosContornos) > 0: todosContornosLinhas.pop(0) todosContornos.pop(0) roiAlunosLinhas = todosContornosLinhas roiAlunos = todosContornos if len(roiAlunos) > 1: (x1, _, _, _) = todosContornosLinhas[0] (x2, _, _, _) = todosContornosLinhas[1] if (x1 > x2): temp = roiAlunos[0] roiAlunos[0] = roiAlunos[1] roiAlunos[1] = temp temp = roiAlunosLinhas[0] roiAlunosLinhas[0] = roiAlunosLinhas[1] roiAlunosLinhas[1] = temp if (roiAlunos[0].shape[1] > IMGX * 0.65): largura = roiAlunos[0].shape[1] altura = roiAlunos[0].shape[0] roi1 = roiAlunos[0][0:altura, 0:int(largura / 2)] roi2 = roiAlunos[0][0:altura, int(largura / 2):largura] roiAlunos = [] roiAlunos.append(roi1) roiAlunos.append(roi2) (x, y, w, h) = roiAlunosLinhas[0] roiLinhas1 = (x, y, int(w / 2), h) roiLinhas2 = (int(w / 2), y, w, h) roiAlunosLinhas = [] roiAlunosLinhas.append(roiLinhas1) roiAlunosLinhas.append(roiLinhas2) else: quit( "Folha ilegível, não foi possivel encontrar nenhuma tabela de alunos" ) return roiAlunos, roiAlunosLinhas
def get_sub_answer_card_cnts(img_path): """ 获得答题卡的子区域 # findContours 函数详解:https://blog.csdn.net/laobai1015/article/details/76400725 # approxPolyDP 多边形近似 https://blog.csdn.net/kakiebu/article/details/79824856 Args: img ([type]): 图片 Returns: [type]: 答题卡的左右答题区域轮廓 """ image = cv2.imread(img_path) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # warped_answer_image_1 = four_point_transform(gray, answer_contour_1.reshape(4, 2)) # 二值化 thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] # 在二值图像中查找轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立 thresh_cnts, _ = cv2.findContours(thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) cnt_size = 0 sub_answer_cnts = [] if len(thresh_cnts) > 0: # 将轮廓按大小, 降序排序 thresh_cnts = sorted(thresh_cnts, key=cv2.contourArea, reverse=True) for c in thresh_cnts: cnt_size = cnt_size + 1 # arcLength 计算周长 peri = cv2.arcLength(c, True) # 计算轮廓的边界框 (x, y, w, h) = cv2.boundingRect(c) print((x, y, w, h)) # 之前寻找到的轮廓可能是多边形,现在通过寻找近似轮廓,得到期望的四边形 approx = cv2.approxPolyDP(c, 0.02 * peri, True) # 只提取近似轮廓为四边形的区域, 且轮廓长度大于指定长度 if len(approx) == 4 and w > 1300: print("轮廓周长:", peri, '宽:', w) print('原始轮廓的边数:', len(c), ', 近似轮廓的边数:', len(approx)) sub_answer_cnts.append(approx) # 只处理前20个最大轮廓 if cnt_size >= 20: break # 从上到下,将轮廓排序 print(type(sub_answer_cnts)) sub_answer_cnts = sort_contours(sub_answer_cnts, method="top-to-bottom")[0] print(type(sub_answer_cnts)) return sub_answer_cnts
def corrigeAlinhamento(img): imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(imgGray, 150, 255, cv2.THRESH_BINARY_INV) contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0] contours = utils.sort_contours(contours, method="top-to-bottom")[0] if len(contours) > 0: todosContornos = [] for c in contours: perimetro = cv2.arcLength(c, True) area = cv2.contourArea(c) if (perimetro > 1000 and area > 100000): (x, y, w, h) = cv2.boundingRect(c) roi = img[y:y + h, x:x + w] todosContornos.append(roi) cabecalho = todosContornos[0] grayCabecalho = cv2.cvtColor(cabecalho, cv2.COLOR_BGR2GRAY) grayCabecalho = np.float32(grayCabecalho) corners = cv2.goodFeaturesToTrack(grayCabecalho, 500, 0.02, 20) corners = np.int0(corners) if len(corners) > 0: leftCorners = [] rightCorners = [] larguraCabecalho = cabecalho.shape[1] for corner in corners: x, y = corner.ravel() if x < 50: leftCorners.append(y) if x > (larguraCabecalho - 50): rightCorners.append(y) leftCorners.sort() rightCorners.sort() leftCorner = leftCorners[0] rightCorner = rightCorners[0] correcao = 0 if leftCorner > rightCorner: correcao = -leftCorner if rightCorner > leftCorner: correcao = rightCorner correcao = correcao * 0.033 print("correcao ->" + str(correcao)) img = imutils.rotate(img, correcao) img = img[int(IMGY * 0.05):IMGY - int(IMGY * 0.05), int(IMGX * 0.02):IMGX - int(IMGX * 0.02)] else: quit("Folha ilegível, falha no alinhamento") return img
def get_answer_card_cnts(img): """ 获得答题卡的左右答题区域 # findContours 函数详解:https://blog.csdn.net/laobai1015/article/details/76400725 # approxPolyDP 多边形近似 https://blog.csdn.net/kakiebu/article/details/79824856 Args: img ([type]): 图片 Returns: [type]: 答题卡的左右答题区域轮廓 """ # 检测图片中的最外围轮廓 cnts, _ = cv2.findContours(img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) print("原始图片检测的轮廓总数:", len(cnts)) if len(cnts) == 0: return None # 提取的轮廓总数 contour_size = 0 # 检测到的左右答题区域轮廓 answer_cnts = [] # 将轮廓按大小, 降序排序 cnts = sorted(cnts, key=cv2.contourArea, reverse=True) for c in cnts: # arcLength 计算周长 peri = cv2.arcLength(c, True) # print("轮廓周长:", peri) # 之前寻找到的轮廓可能是多边形,现在通过寻找近似轮廓,得到期望的四边形 approx = cv2.approxPolyDP(c, 0.02 * peri, True) # print('原始轮廓的边数:', len(c), ', 近似轮廓的边数:', len(approx)) # 当近似轮廓为4时,代表是需要提取的矩形区域 if len(approx) == 4: contour_size = contour_size + 1 answer_cnts.append(approx) # 只提取答题卡中的最大两个轮廓 if contour_size == 2: break answer_cnts = sort_contours(answer_cnts, method="left-to-right")[0] return answer_cnts
cv_show('ref',ref) #二值图像 ref=cv2.threshold(ref,10,255,cv2.THRESH_BINARY_INV)[1] cv_show('ref',ref) #计算轮廓 #cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图) #cv2.RETR_EXTERNAL只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE只保留终点坐标 #返回的list中每个元素都是图像中的一个轮廓 # ref_, refCnts,hierarchy=cv2.findContours(ref.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) cv2.drawContours(img,refCnts,-1,(0,0,255),3) cv_show('img',img) print(np.array(refCnts).shape) refCnts=utils.sort_contours(refCnts,method="left-to-right")[0]#排序从左到右,从上到下 digits={} ''' 第一个参数:img是原图 第二个参数:(x,y)是矩阵的左上点坐标 第三个参数:(x+w,y+h)是矩阵的右下点坐标 第四个参数:(0,255,0)是画线对应的rgb颜色 ''' #遍历每一个轮廓 for(i,c) in enumerate(refCnts): #计算外接矩形并且resize成合适大小 (x,y,w,h)=cv2.boundingRect(c) roi=ref[y:y+h,x:x+w] roi=cv2.resize(roi,(57,58))
def refine_accNum(file_name, img_for_box_extraction_path, dir_path, img): og_img = img height, width = img.shape[:2] (thresh, img) = cv2.threshold(img, 160, 255, cv2.THRESH_BINARY) # Invert the image img_bin_inv = 255 - img # Defining a kernel length kernel_length = np.array(img).shape[1] // 20 kernel_length_vertical = height // 2 kernel_length_horizontal = width // 4 # A verticle kernel of (1 X kernel_length), which will detect all the verticle lines from the image. verticle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, kernel_length_vertical)) # A horizontal kernel of (kernel_length X 1), which will help to detect all the horizontal line from the image. hori_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_length_horizontal, 1)) # A kernel of (3 X 3) ones. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) # Morphological operation to detect vertical lines from an image img_temp1 = cv2.erode(img, verticle_kernel, iterations=1) # utils.display_image('display_image', img_temp1) verticle_lines_img = cv2.dilate(img_temp1, verticle_kernel, iterations=1) (thresh, verticle_lines_img) = cv2.threshold(verticle_lines_img, 32, 255, cv2.THRESH_BINARY) # utils.display_image('display_image', verticle_lines_img) # Morphological operation to detect horizontal lines from an image img_temp2 = cv2.erode(img, hori_kernel, iterations=1) # utils.display_image('display_image', img_temp2) horizontal_lines_img = cv2.dilate(img_temp2, hori_kernel, iterations=1) (thresh, horizontal_lines_img) = cv2.threshold(horizontal_lines_img, 32, 255, cv2.THRESH_BINARY) # utils.display_image('display_image', horizontal_lines_img) # Weighting parameters, this will decide the quantity of an image to be added to make a new image. alpha = 0.5 beta = 1.0 - alpha # This function helps to add two image with specific weight parameter to get a third image as summation of two image. img_final_bin = cv2.addWeighted(verticle_lines_img, alpha, horizontal_lines_img, beta, 0.0) # utils.display_image('display_image', img_final_bin) # Find contours for image, which will detect all the boxes im2, contours, hierarchy = cv2.findContours(img_final_bin, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # Sort all the contours by top to bottom. if (len(contours) != 0): (contours, boundingBoxes) = utils.sort_contours(contours, method="top-to-bottom") idx = 0 for c in contours: # Returns the location and width,height for every contour x, y, w, h = cv2.boundingRect(c) if w < width // 5 or h < height // 5: continue new_img = img_final_bin[y:y + h, x:x + w] # utils.display_image('display_image', new_img) # utils.store_img(dir_path, file_name, new_img, "date") # cv2.imwrite(dir_path + "/date/" + img_for_box_extraction_path + '.tif', new_img) # (thresh, new_img) = cv2.threshold(new_img, 32, 255,cv2.THRESH_BINARY) # utils.display_image('display_image', new_img) final_img = og_img[y:y + h, x:x + w] - new_img # utils.display_image('display_image', final_img) (thresh, final_img) = cv2.threshold(final_img, 32, 255, cv2.THRESH_BINARY) # utils.display_image('display_image', final_img) idx = idx + 1 print(file_name) # tess.test(file_name, img) # utils.store_img(dir_path, file_name, img, "refined_acc") utils.display_image('display_image', final_img) # remove_lines(final_img) # if idx == 2: break
def find_boxes(file_name, img_for_box_extraction_path, dir_path, img): # Read the image # path = file_name # print(path) # img = cv2.imread(path , 0) # height, width = img.shape[:2] # img = cv2.resize(img,(width//2, height//2), interpolation = cv2.INTER_AREA) height, width = img.shape[:2] og_img = img # Thresholding the image (thresh, img_bin) = cv2.threshold(img, 160, 255, cv2.THRESH_BINARY) # Invert the image img_bin = 255 - img_bin #utils.display_image('display_image', img_bin) extraction_img = img_bin kernel = cv2.getStructuringElement( cv2.MORPH_CROSS, (3, 3) ) # to manipulate the orientation of dilution , large x means horizonatally dilating more, large y means vertically dilating more dilated = cv2.dilate( img_bin, kernel, iterations=2) # dilate , more the iteration more the dilation # utils.display_image('display_image', dilated) # utils.store_img(dir_path, "1" + file_name, dilated, "boxes_temp") img_bin = dilated img_bin = cv2.GaussianBlur(img_bin, (5, 5), 0) # utils.display_image('display_image', img_bin) # utils.store_img(dir_path, "2" + file_name, img_bin, "boxes_temp") # Defining a kernel length kernel_length = np.array(img).shape[1] // 80 # A verticle kernel of (1 X kernel_length), which will detect all the verticle lines from the image. verticle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, kernel_length)) # A horizontal kernel of (kernel_length X 1), which will help to detect all the horizontal line from the image. hori_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_length, 1)) # A kernel of (3 X 3) ones. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) # Morphological operation to detect vertical lines from an image img_temp1 = cv2.erode(img_bin, verticle_kernel, iterations=2) # utils.display_image('display_image', img_temp1) verticle_lines_img = cv2.dilate(img_temp1, verticle_kernel, iterations=2) (thresh, verticle_lines_img) = cv2.threshold(verticle_lines_img, 127, 255, cv2.THRESH_BINARY) # utils.display_image('display_image', verticle_lines_img) # utils.store_img(dir_path, "3" + file_name, verticle_lines_img, "boxes_temp") # Morphological operation to detect horizontal lines from an image img_temp2 = cv2.erode(img_bin, hori_kernel, iterations=2) # utils.display_image('display_image', img_temp2) horizontal_lines_img = cv2.dilate(img_temp2, hori_kernel, iterations=2) (thresh, horizontal_lines_img) = cv2.threshold(horizontal_lines_img, 127, 255, cv2.THRESH_BINARY) # utils.display_image('display_image', horizontal_lines_img) # utils.store_img(dir_path, "4" + file_name, horizontal_lines_img, "boxes_temp") # Weighting parameters, this will decide the quantity of an image to be added to make a new image. alpha = 0.5 beta = 1.0 - alpha # This function helps to add two image with specific weight parameter to get a third image as summation of two image. img_final_bin = cv2.addWeighted(verticle_lines_img, alpha, horizontal_lines_img, beta, 0.0) # utils.display_image('display_image', img_final_bin) img_final_bin = cv2.erode(~img_final_bin, kernel, iterations=2) # utils.display_image('display_image', img_final_bin) (thresh, img_final_bin) = cv2.threshold(img_final_bin, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) # utils.display_image('display_image', img_final_bin) # utils.store_img(dir_path, "5" + file_name, img_final_bin, "boxes_temp") # Find contours for image, which will detect all the boxes im2, contours, hierarchy = cv2.findContours(img_final_bin, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #utils.display_image('display_image', im2) # Sort all the contours by top to bottom. (contours, boundingBoxes) = utils.sort_contours(contours, method="top-to-bottom") idx = 0 account_no_flag = False date_flag = False amount_flag = False account_number_list = [] amount_list = [] for c in contours: # Returns the location and width,height for every contour x, y, w, h = cv2.boundingRect(c) if w < width // 20 or h < height // 20: continue if (isAccountNumber(width, height, x, y, w, h)): account_number_list.append(c) # print("Account Number") new_img = extraction_img[y:y + h, x:x + w] if (isAmount(width, height, x, y, w, h)): amount_list.append(c) new_img = extraction_img[y:y + h, x:x + w] if (isDate(width, height, x, y, w, h) and not date_flag): print("Date") date_flag = True new_img = og_img[y:y + h, x:x + w] # new_img = extraction_img[y:y+h, x:x+w] # utils.display_image('display_image', new_img) utils.store_img(dir_path, file_name, new_img, "date1") account_number_list = utils.sort_contours_area(account_number_list) amount_list = utils.sort_contours_area(amount_list) if len(account_number_list) != 0: for i in range(len(account_number_list)): x, y, w, h = cv2.boundingRect(account_number_list[0]) new_img = extraction_img[y:y + h, x:x + w] # utils.display_image('display_image', new_img) # utils.store_img(dir_path, file_name, new_img, "accNum") if len(amount_list) != 0: x, y, w, h = cv2.boundingRect(amount_list[0]) new_img = extraction_img[y:y + h, x:x + w]
def refine_date(file_name, img_for_box_extraction_path, dir_path, img): height, width = img.shape[:2] img = cv2.resize(img, (width * 2, height * 2), interpolation=cv2.INTER_LINEAR) height, width = img.shape[:2] (thresh, img) = cv2.threshold(img, 160, 255, cv2.THRESH_BINARY_INV) # utils.display_image('display_image', img) og_img = img # Invert the image img_bin_inv = 255 - img # Defining a kernel length kernel_length = np.array(img).shape[1] // 20 kernel_length_vertical = height // 2 kernel_length_horizontal = width // 4 # A verticle kernel of (1 X kernel_length), which will detect all the verticle lines from the image. verticle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, kernel_length_vertical)) # A horizontal kernel of (kernel_length X 1), which will help to detect all the horizontal line from the image. hori_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_length_horizontal, 1)) # A kernel of (3 X 3) ones. kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (2, 2)) img_temp = cv2.dilate(img, kernel, iterations=1) # utils.display_image('display_image', img_temp) # Morphological operation to detect horizontal lines from an image img_temp2 = cv2.erode(img_temp, hori_kernel, iterations=1) # utils.display_image('display_image', img_temp2) horizontal_lines_img = cv2.dilate(img_temp2, hori_kernel, iterations=1) (thresh, horizontal_lines_img) = cv2.threshold(horizontal_lines_img, 160, 255, cv2.THRESH_BINARY) # utils.display_image('display_image', horizontal_lines_img) im2, contours, hierarchy = cv2.findContours(horizontal_lines_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # Sort all the contours by top to bottom. (contours, boundingBoxes) = utils.sort_contours(contours, method="top-to-bottom") if len(contours) > 1: x1, y1, w1, h1 = cv2.boundingRect(contours[0]) x2, y2, w2, h2 = cv2.boundingRect(contours[len(contours) - 1]) print(cv2.boundingRect(contours[0])) print(cv2.boundingRect(contours[len(contours) - 1])) new_img = img_temp[y1 + h1:y2, x2:x1 + w2] # utils.display_image('display_image', new_img) # utils.store_img(dir_path, file_name, new_img, "date") # cv2.imwrite(dir_path + "/date/" + img_for_box_extraction_path + '.tif', new_img) # (thresh, new_img) = cv2.threshold(new_img, 32, 255,cv2.THRESH_BINARY) # utils.display_image('display_image', new_img) final_img = new_img # utils.display_image('display_image', final_img) # (thresh, final_img) = cv2.threshold(final_img, 32, 255,cv2.THRESH_BINARY) # utils.display_image('display_image', final_img) #final_image = remove_lines(final_img) # utils.store_img(dir_path, file_name, final_img, "date8") utils.store_img(dir_path, file_name, final_img, "date2") img_temp = final_img
def get_underline(img_for_extraction_path, file_name, dir_path, img): # height, width = og_img.shape[:2] # og_img = cv2.resize(og_img,(width//2, height//2), interpolation = cv2.INTER_AREA) height, width = img.shape[:2] og_img = slicing.slice_image_get_remaining(img) og_image_contours = og_img utils.display_image('display_image', og_img) # Thresholding the image (thresh, img_bin) = cv2.threshold(og_img, 160, 255, cv2.THRESH_BINARY) # Invert the image utils.display_image('display_image', img_bin) img_bin_inv = 255 - img_bin img_bin_inv_final = 255 - img_bin utils.display_image('display_image', img_bin_inv) # utils.store_img(dir_path, str(1) + "_" + img_for_extraction_path, img_bin_inv, "images_for_paper") img_bin_inv_blur = cv2.GaussianBlur(img_bin_inv, (3, 3), 0) utils.display_image('display_image', img_bin_inv_blur) kernel = cv2.getStructuringElement( cv2.MORPH_CROSS, (5, 2) ) # to manipulate the orientation of dilution , large x means horizonatally dilating more, large y means vertically dilating more img_bin_inv_blur_dilated = cv2.dilate( img_bin_inv_blur, kernel, iterations=3) # dilate , more the iteration more the dilation utils.display_image('display_image', img_bin_inv_blur_dilated) # utils.store_img(dir_path, str(2) + "_" + img_for_extraction_path, img_bin_inv_blur_dilated, "images_for_paper") kernel_length = np.array(img_bin).shape[1] // 5 hori_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_length, 1)) img_temp_horizontal = cv2.erode(img_bin_inv_blur_dilated, hori_kernel, iterations=1) utils.display_image('display_image', img_temp_horizontal) # utils.store_img(dir_path, str(3) + "_" + img_for_extraction_path, img_temp_horizontal, "images_for_paper") horizontal_lines_img = cv2.dilate(img_temp_horizontal, hori_kernel, iterations=1) utils.display_image('display_image', horizontal_lines_img) # utils.store_img(dir_path, img_for_extraction_path, horizontal_lines_img, "handwritten") (thresh, horizontal_lines_img) = cv2.threshold(horizontal_lines_img, 32, 255, cv2.THRESH_BINARY) utils.display_image('display_image', horizontal_lines_img) utils.store_img(dir_path, str("3a") + "_" + img_for_extraction_path, horizontal_lines_img, "images_for_paper") horizontal_lines_img = cv2.GaussianBlur(horizontal_lines_img, (5, 5), 0) utils.display_image('display_image', horizontal_lines_img) edges = cv2.Canny(horizontal_lines_img, 127, 255) lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 30, minLineLength=height // 1.5) img_bin_inv_contours = img_bin_inv # if lines is None: # return # for line in lines: # x1, y1, x2, y2 = line[0] # cv2.line(img_bin_inv_contours, (x1, y1), (x2, y2), (0, 255, 0), 3) image, contours, hierarchy = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) utils.display_image('display_image', image) # utils.store_img(dir_path, str(4) + "_" + img_for_extraction_path, image, "images_for_paper") cv2.drawContours(img_bin_inv_contours, contours, -1, (255, 255, 255), 3) utils.display_image('display_image', img_bin_inv_contours) # Sort all the contours by top to bottom. (contours, boundingBoxes) = utils.sort_contours(contours, method="top-to-bottom") idx = 0 underline = "underline" flag = False amount_image = None previous = None # utils.display_image1(img_bin_inv_final) for contour in contours: # get rectangle bounding contour [x, y, w, h] = cv2.boundingRect(contour) # Don't plot small false positives that aren't text if w < width / (2): continue if ((y - (height // 8)) > 0): utils.display_image( 'captcha_result', img_bin_inv_final[y - (height // 10):y + h + (height // 100), width // 10:width - width // 5]) # utils.display_image('captcha_result', crop_img) # utils.store_img(dir_path, underline + "_" + str(idx) + "_" + img_for_extraction_path, crop_img, "handwritten_payee") else: # crop_img = img_bin_inv_final[0 : y + h + (height // 100), x : x + w] utils.display_image( 'captcha_result', img_bin_inv_final[0:y + h + (height // 100), width // 10:width - width // 5]) utils.display_image( 'captcha_result', img_bin_inv_final[y - (height // 10):y + h + (height // 100), width // 10:width - width // 5]) # y_act = y - (height // 12) # h_act = y_act + (height // 12) + (h + (height // 100)) if flag: if previous is None: # print ("Previous is None") previous = [0, y, width, h] else: # print (previous) # print ([0, y, width, h]) overlap = utils.find_overlap(img_bin_inv_final, previous, [0, y, width, h]) # previous = [0, y, width, h] if overlap > 0.1: continue else: previous = [0, y, width, h] if not flag: # draw rectangle around contour on original image # cv2.rectangle(og_image_contours, (x, y , (x + w, y + h + (height // 100), (0, 0, 0), 2) flag = True # delta = (height // 100) if ((y - (height // 8)) > 0): crop_img = img_bin_inv_final[y - (height // 10):y + h + (height // 100), width // 10:width - width // 5] # utils.display_image('captcha_result', crop_img) # utils.store_img(dir_path, underline + "_" + str(idx) + "_" + img_for_extraction_path, crop_img, "handwritten_payee") else: # crop_img = img_bin_inv_final[0 : y + h + (height // 100), x : x + w] crop_img = img_bin_inv_final[0:y + h + (height // 100), width // 10:width - width // 5] # utils.display_image('captcha_result', crop_img) # utils.store_img(dir_path, underline + "_" + str(idx) + "_" + img_for_extraction_path, crop_img, "handwritten_payee") else: if ((y - (height // 8)) > 0): crop_img = img_bin_inv_final[y - (height // 12):y + h + (height // 100), :] else: # crop_img = img_bin_inv_final[0 : y + h + (height // 100), x : x + w] crop_img = img_bin_inv_final[0:y + h + (height // 100), :] # utils.display_image('captcha_result', crop_img) # print("Underline") # utils.store_img(dir_path, underline + "_" + str(idx) + "_" + img_for_extraction_path, crop_img, "handwritten") if amount_image is None: amount_image = crop_img else: h1, w1 = amount_image.shape[:2] h2, w2 = crop_img.shape[:2] vis = np.zeros((max(h1, h2), w1 + w2), np.uint8) vis[:h1, :w1] = amount_image vis[:h2, w1:w1 + w2] = crop_img amount_image = vis # utils.display_image('captcha_result', amount_image) # print("Underline") # utils.store_img(dir_path, underline + "_" + str(idx) + "_" + img_for_extraction_path, crop_img, "handwritten") idx = idx + 1 height, width = amount_image.shape[:2] # utils.display_image('captcha_result', amount_image) amount_image[:, width - ((width) // 5):] = 0 # utils.display_image('captcha_result', amount_image) # width//2 - (width//2)//20 amount_image[:, width // 2 - (width // 2) // 15:width // 2 + (width // 2) // 15] = 0 # utils.display_image('captcha_result', amount_image) # utils.store_img(dir_path, underline + "_" + str(idx) + "_" + img_for_extraction_path, amount_image, "handwritten_concatenated") if idx == 4: print(file_name) amount_image = amount_image[:, :width // 2]
def remove_underline_name(img_for_extraction_path, file_name, dir_path, img): height, width = img.shape[:2] img = img[height // 20:, width // 20:width - width // 5] final_img = img temp_image = img kernel = cv2.getStructuringElement( cv2.MORPH_CROSS, (5, 1) ) # to manipulate the orientation of dilution , large x means horizonatally dilating more, large y means vertically dilating more img_dilated = cv2.dilate( img, kernel, iterations=2) # dilate , more the iteration more the dilation # utils.display_image('display_image', img_dilated) kernel_length = np.array(img_dilated).shape[1] // 5 hori_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_length, 1)) img_temp_horizontal = cv2.erode(img_dilated, hori_kernel, iterations=1) # utils.display_image('display_image', img_temp_horizontal) horizontal_lines_img = cv2.dilate(img_temp_horizontal, hori_kernel, iterations=3) # utils.display_image('display_image', horizontal_lines_img) new_img = img - horizontal_lines_img # utils.display_image('display_image', new_img) final_img = new_img kernel = cv2.getStructuringElement( cv2.MORPH_RECT, (5, 5) ) # to manipulate the orientation of dilution , large x means horizonatally dilating more, large y means vertically dilating more dilated_img = cv2.dilate(new_img, kernel, iterations=2) # utils.display_image('display_image', dilated_img) new_img = dilated_img im2, contours, hierarchy = cv2.findContours(new_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) #utils.display_image('display_image', im2) (contours, boundingBoxes) = utils.sort_contours(contours, method="left_to_right") # contours = utils.sort_contours_area(contours) length = len(contours) trim_size = length // 5 print("Length : " + str(length) + " -- trim_size : " + str(trim_size)) for i in range(0, length): # and i < length - 2*trim_size if (i >= trim_size): continue contour = contours[i] # get rectangle bounding contour [x, y, w, h] = cv2.boundingRect(contour) if w > width // 50 and h > height // 2: continue # Don't plot small false positives that aren't text # if w < width//50 or h < height//3: # continue # draw rectangle around contour on original image cv2.rectangle(temp_image, (x, y), (x + w, y + h), (255, 255, 255), 2) crop_img = new_img[y:y + h, x:x + w] # utils.display_image('captcha_result', crop_img) # new_img[y : y + h, x : x + w] = 0 final_img[y:y + h, x:x + w] = 0 # utils.display_image('captcha_result', new_img) print("contour") # utils.display_image('captcha_result', final_img) utils.store_img(dir_path, img_for_extraction_path, final_img, "name")
threshold, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU) print(threshold) cv2.imshow('binary', binary) # 获取模板图像的外轮廓, 保留终点坐标 ref, refCnts, hierarchy = cv2.findContours(binary.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cv2.imshow('ref', ref) # 画出边框 cv2.drawContours(tpl, refCnts, -1, (0, 0, 255), 3) cv2.imshow('tpl_Contours', tpl) # print(np.array(refCnts)) # 10. # 对模板图像进行排序, 方便从0-9对应存储 refCnts = utils.sort_contours(refCnts, method="left-to-right")[0] digits = {} # 遍历模板图形的每一个轮廓 for (k, v) in enumerate(refCnts): x, y, w, h = cv2.boundingRect(v) roi = ref[y:y + h, x:x + w] roi = cv2.resize(roi, (57, 88)) # 按 method 方法进行存储, 每个数字代表一个模板 digits[k] = roi # step2: 预处理测试集图像 # 根据卡上字体大小, 初始化卷积核 rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3)) sqKerbel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
if __name__ == '__main__': # load color image base_address = Path('Inputs') image_paths = base_address.glob('*.png') results_save_dir = Path('results') results_save_dir.mkdir(parents=True, exist_ok=True) dim = (820, 600) for image_path in image_paths: print(image_path) original_image = cv2.imread(str(image_path)) original_image = cv2.resize(original_image, dim, interpolation=cv2.INTER_AREA) image_color = original_image.copy() processed_image = preprocess_image(image=original_image) img_final_bin = find_boxes(processed_image) # Find contours for image, which will detect all the boxes contours, hierarchy = cv2.findContours(img_final_bin, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # Sort all the contours by top to bottom. (contours, boundingBoxes) = sort_contours(contours, method="top-to-bottom") save_results(save_dir=results_save_dir, image=image_color, all_contours=contours, image_name=image_path.name)
def processaAlunos(img): todosAlunos = [] alunosPresentes = [] imgFinal = img.copy() imgCerto = ff.carregaImagemCerto() linhasHorizontais, linhas = folhaPresenca.filtroDeLinhas(img) roiAlunos, roiAlunosLinhas = folhaPresenca.encontraTabelasAlunos( img, linhas) folhaInvalida = 0 contador = 1 #percorre as tabelas dos alunos encontradas for r in range(len(roiAlunos)): linhasAlunos = extraiLinhasAlunosIndividual(linhasHorizontais, roiAlunosLinhas[r]) larg = roiAlunos[r].shape[1] #percorre as linhas que definem cada espaço do aluno for i in range(len(linhasAlunos) - 1): (x1, Yi, x2, y2) = linhasAlunos[i] (x1, y1, x2, Yf) = linhasAlunos[i + 1] altura = Yf - Yi if altura < int(IMGY * 0.005): continue #extrai um aluno consuante as linhas Aluno = roiAlunos[r][Yi:Yf, 5:larg - 10] #extrai número de aluno consuante coordenadas fixas. nrAluno = Aluno[int(round(altura * 0.1)):int(round(altura * 0.93)), int(round(larg * 0.1)):int(round(larg * 0.29))] #aproximação exata ao local do número de aluno nrAluno = encontraNumeroAluno(nrAluno) nrAlunoGray = cv2.cvtColor(nrAluno, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(nrAlunoGray, 130, 255, cv2.THRESH_BINARY_INV) contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) contours = imutils.grab_contours(contours) if len(contours) > 0: contours = utils.sort_contours(contours, method="left-to-right")[0] larguraNumero = nrAluno.shape[1] / 10 listaNr = [] #percorre os números encontrados for c in contours: (x, y, w, h) = cv2.boundingRect(c) roi = nrAlunoGray[y:y + h, x:x + w] roi = cv2.addWeighted(roi, 1, roi, 0, -35) if cv2.arcLength(c, True) > 25: if (w > larguraNumero + (larguraNumero * 0.5)): primeiroNumero = nrAlunoGray[y:y + h, x:int(x + (w / 2))] primeiroNumero = cv2.addWeighted( primeiroNumero, 1, primeiroNumero, 0, -35) segundoNumero = nrAlunoGray[y:y + h, int(x + (w / 2)):x + w] segundoNumero = cv2.addWeighted( segundoNumero, 1, segundoNumero, 0, -35) listaNr.append(identificaNumeros(primeiroNumero)) listaNr.append(identificaNumeros(segundoNumero)) else: listaNr.append(identificaNumeros(roi)) n = "" for j in listaNr: n = n + str(j) if len(n) == 10: try: numero_Aluno = int(n) except ValueError: print( "Não foi possível ler o número do aluno corretamente") numero_Aluno = 0 assinatura = Aluno[int(round(altura * 0.25)):int(round(altura * 0.94)), int(round(larg * 0.74)):int(round(larg * 0.97))] assinado, incerto = verificaAssinatura(assinatura) todosAlunos.append(numero_Aluno) if assinado: ff.folhaFinal(imgFinal, roiAlunosLinhas[r], Yi, imgCerto) alunosPresentes.append(numero_Aluno) print( str(contador) + " - " + str(numero_Aluno) + " = Assinatura incerta, verificar") if incerto else print( str(contador) + " - " + str(numero_Aluno) + " = PRESENTE") if assinado else print( str(contador) + " - " + str(numero_Aluno)) contador += 1 else: numero_Aluno = int(n) print( str(contador) + " - Não foi possível ler o número do aluno corretamente -> " + str(numero_Aluno)) folhaInvalida += 1 contador += 1 if folhaInvalida > len(todosAlunos): quit("folha com problemas") imgFinal = cv2.resize(imgFinal, (1000, 1200)) cv2.imshow("imagem Final", imgFinal) return todosAlunos, alunosPresentes