Python 偵測邊緣的方式去除白色無效資訊:以mammography為例

markdown #說明 前一篇以影像處理的方法,去做去除文字,主要是偵測RGB的值,寫 rule的方法去去除,那這一篇是用找尋邊緣的方式去除文字。 #操作流程 ##Code ``` import cv2 import numpy as np def draw_contours(img, cnts): # conts = contours img = np.copy(img) img = cv2.drawContours(img, cnts, -1, (0, 255, 0), 2) return img def draw_min_rect_circle(img, cnts): # conts = contours img = np.copy(img) for cnt in cnts: # 這邊的 cnts 是一整組的輪廓,裡面有很多個點,所以是對每一個點去做 for 迴圈 x, y, w, h = cv2.boundingRect(cnt) # cv2.boundingRect這個函數為替輪廓加入邊框,用來標示圖片中特定物體的法 # 輸入值是輪廓,輸出值為,一組四個值,分別表示左上角的x與y,和寬和長 # 參考: https://chtseng.wordpress.com/2016/12/05/opencv-contour%E8%BC%AA%E5%BB%93/ #cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) # blue # cv2.rectangle 這個函數是繪製方框,輸入值為 影像,和頂點座標,和對項座標,框線的顏色,框線的寬度 =這裡是藍色框 rectangle = ([[x, y], [x + w, y], [x, y + h], [x + w, y + h]]) area1 = np.array([[x, y], [(x + w), y], [x, (y + h)], [(x + w), (y + h)]]) img2=cv2.fillPoly(img, [area1], (0, 0, 0)) cv2.namedWindow('3', cv2.WINDOW_NORMAL) cv2.resizeWindow("3", 640, 480) cv2.imshow("3", img) # cv2.waitKey(1943) cv2.waitKey(0) cv2.imwrite("result3.jpg", img) min_rect = cv2.minAreaRect(cnt) # 最小矩陣,會返回 ( (最小外接矩形的中心座標),(寬和高),旋轉角度 ) # 參考:https://www.itread01.com/content/1548357888.html min_rect = np.int0(cv2.boxPoints(min_rect)) # 輪廓點原本是浮點數(有小數點的),轉換成整數 #area1 = np.array([[x, y], [(x + w), y], [x, (y + h)], [(x + w), (y + h)]]) img2 = cv2.fillPoly(img, [min_rect], (0, 0, 0)) cv2.namedWindow('3', cv2.WINDOW_NORMAL) cv2.resizeWindow("3", 640, 480) cv2.imshow("3", img) # cv2.waitKey(1943) cv2.waitKey(0) cv2.imwrite("result5.jpg", img) #cv2.drawContours(img, [min_rect], 0, (0, 255, 0), 2) # green #畫輪廓#綠色 (x, y), radius = cv2.minEnclosingCircle(cnt) # 這個和剛剛的很相似,剛剛是畫矩形,這裡是畫圓形 # 這邊畫圓形,所以返回值是圓心的座標(x,y) 和半徑 center, radius = (int(x), int(y)), int(radius) # center and radius of minimum enclosing circle #img = cv2.circle(img, center, radius, (0, 0, 255), 2) # red #畫成紅色的圓形 return img # 返回影像所以這個影像包含了藍色框線和綠色的矩形和紅色的圓形 def draw_approx_hull_polygon(img, cnts): # img = np.copy(img) img = np.copy(img) img = np.zeros(img.shape, dtype=np.uint8) # img2=np.zeros(img2.shape, dtype=np.uint8) #cv2.drawContours(img, cnts, -1, (255, 0, 0), 2) # blue # cv2.drawContours 這個函式是用來繪製輪廓的,根據邊界點繪製任何形狀 # 輸入的參數,第一個是原始影像,第二個是輪廓這是一個列表的資料型態, # 第三個是輪廓的索引(index),如果設置-1,就是畫全部的輪廓,最後一個參數是輪廓的顏色=(255,0,0)藍色和厚度=2 # 參考 https://www.kancloud.cn/aollo/aolloopencv/272892 print(cnts) cv2.fillPoly(img, cnts, (0, 0, 0)) cv2.imwrite("result4.jpg", img) min_side_len = img.shape[0] / 32 # 多邊形邊長的最小值 min_poly_len = img.shape[0] / 16 # 多邊形周長的最小值 min_side_num = 3 # 多邊形邊數的最小值 approxs = [cv2.approxPolyDP(cnt, min_side_len, True) for cnt in cnts] # 以最小邊長為限制繪製多邊形 # cv2.approxPolyDP 函數,這個是做對多邊形進行逼近,可以為多邊形加上限制 # 導致原本的多邊形的點數很多,經由這個函數後會減少邊的點數,代表邊也減少了 # 舉例來說可能有一個80邊的多邊形,經由 cv2.approxPolyDP 函數 加上限制後,就會可能變成8邊的多邊形 # 參考: https://gogoprivateryan.blogspot.com/2015/08/opencv-2-opencv-python.html approxs = [approx for approx in approxs if cv2.arcLength(approx, True) > min_poly_len] # 篩選出周長大於 min_poly_len 的多邊形 approxs = [approx for approx in approxs if len(approx) > min_side_num] # 篩選出邊長大於 min_side_num 的多邊形 #cv2.polylines(img, approxs, True, (0, 255, 0), 2) # green #繪製多邊形輪廓綠色的 cv2.fillPoly(img, approxs, 1) hulls = [cv2.convexHull(cnt) for cnt in cnts] # cv2.convexHull這函數可以找出圖的凸多邊形框,類似找到中心點然後包含所有的輪廓點的最小框 # 參考:https://gogoprivateryan.blogspot.com/2015/08/opencv-2-opencv-python.html # 網址裡面有一個手長的那個多邊形就是那個概念 print(hulls) #cv2.polylines(img, hulls, True, (0, 0, 255), 2) # red #繪製多邊形輪廓紅色 cv2.fillPoly(img, hulls, 1) cv2.imwrite("result.jpg", img) return img # 最後傳回一張有三個顏色的影像,藍色綠色紅色 ,這裡都是多邊形 def run(): image = cv2.imread('./1.jpg') # 1.讀取影像 thresh = cv2.Canny(image, 600, 700) # 這個canny 後面接三個參數,第一個參數是影像,第二個是最小值,第三個是最大值 # cv2.Canny 參考:https://www.jianshu.com/p/e8e1f2f1c605 # 返回值是偵測到邊緣的影像 # cv2.findContours 輸入的參數有三個,第一個是影像,第二個是輪廓檢索模式,第三個是輪廓近似方法) # 返回值,以前的版本返回值有三個,現在新版返回值是兩個,所以常常直接套用網路上的 code 會有 bug,需要修正 # 這邊的兩個返回值,第一個是影像,第二個是輪廓,每一個輪廓都是一個 Numpy 的數組 => [110 123] 類似這樣的,包含邊界座標 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # cv2.findContours 輸入的參數有三個,第一個是影像,第二個是輪廓檢索模式,第三個是輪廓近似方法) # 返回值,以前的版本返回值有三個,現在新版返回值是兩個,所以常常直接套用網路上的 code 會有 bug,需要修正 # 返回值如果是三個的話,第一個是影像,第二個是輪廓,第三個是輪廓的結構 # 這邊的兩個返回值,第一個是輪廓,第二個是輪廓的結構,每一個輪廓都是一個 Numpy 的數組 => [110 123] 類似這樣的,包含邊界座標 # 參考: https://www.kancloud.cn/aollo/aolloopencv/272892 imgs = [ image, thresh, draw_min_rect_circle(image, contours), # 這裡呼叫函數draw_min_rect_circle,投入兩個參數:影像和輪廓 draw_approx_hull_polygon(image, contours), # 這也是呼叫函數 draw_approx_hull_polygon,投入兩個參數:影像和輪廓 ] for img in imgs: # cv2.imwrite("%s.jpg" % id(img), img) cv2.namedWindow('contours', cv2.WINDOW_NORMAL) cv2.resizeWindow("contours", 640, 480) cv2.imshow("contours", img) # cv2.waitKey(1943) cv2.waitKey(0) if __name__ == '__main__': run() pass ``` ##DEMO

留言