我有一些樣本圖片,如下所示
到現在為止,我已經有了一些代碼,這些代碼采用了模板,并洗掉了邊框,得到了第一個結果
import cv2
import numpy as np
def remove_templates(image)。
templates = ['images/sample1.jpeg'/span>, 'images/sample2.jpeg'/span>]
for模板in模板。
模板 = cv2.imread(template)
h, w, _ = template.shape
res = cv2.matchTemplate(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), cv2.cvtColor(template, cv2.COLOR_BGR2GRAY), cv2.TM_CCOEFF)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
top_left = max_loc
bottom_right = (top_left[0] w, top_left[1] h)
cv2.rectangle(img, top_left, bottom_right, (1, 1, 1), -1)
def crop_borders(img)。
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = 255 * (gray < 128).astype(np.uint8) # 要將文字反轉為白色。
gray = cv2.morphologyEx(grey, cv2.MORPH_OPEN, np.ones((2, 2), dtype=np.uint8)) # 進行噪聲過濾。
canny = cv2.Canny(gray, 0, 150)
coords = cv2.findNonZero(canny) # Find all non-zero points (text)
x, y, w, h = cv2.boundingRect(coords) # Find minimum spanning bounding box[/span]。
rect = img[y:y h, x:x w 20] # Crop the image - note we do this on the original image[/span>] 。
return rect
img = cv2.imread('images/res5.jpg'/span>)
remove_templates(img)
img = crop_borders(img)
cv2.imwrite('output/op1.png', img)
cv2.imwrite('output/op2.png', cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
height = img.shape[0]
width = img.shape[1]
# 將影像切成兩半 # 將影像切成兩半
width_cutoff = (width // 2)
left = img[:, :width_cutoff 5]
右 = img[:, width_cutoff 25:]
cv2.imwrite('output/left.png'/span>, left)
cv2.imwrite('output/right.png', right)
上面的代碼確實給了我第一個結果,但當標志的長寬比或尺寸不同時就會失敗。
我怎樣才能做到這一點,任何幫助將是非常有用的。
我是opencv的新手,所以任何方向都會有幫助。我現在的大部分代碼都是從不同的教程中挑選出來的。如果代碼中存在問題,請指導我。
uj5u.com熱心網友回復:
概念
定義了一個新的 "代碼布丁"。
定義一個函式,將BGR影像處理為二進制影像,并增強方框的邊緣。
定義一個函式,接收BGR影像,并回傳從影像中檢測到的、在特定區域范圍內的輪廓(用前一個函式處理)。
繪制每個輪廓的邊界框,為了裁剪影像,連接所有的輪廓,并獲得所有輪廓的邊界框,以用于切分影像。
代碼
import cv2
import numpy as np
def process(img)。
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_gray[img_gray < 5] = 255return cv2.dilate(cv2.Canny(img_gray, 50, 75), np. ones((4, 4)), iterations= 2)
def get_cnts(img)。
cnts, _ = cv2.findContours(process(img), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
return [cnt for cnt in cnts if 80000 > cv2. contourArea(cnt) > 40000]
img = cv2.imread("image.png"/span>)
cnts = get_cnts(img)
for cnt in cnts:
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(img, (x, y), (x w, y h), (0, 255, 0), 3)
x, y, w, h = cv2.boundingRect(np.concatenate(cnts))
cv2.imshow("Image", img[y: y h, x: x w] )
cv2.waitKey(0)
cv2.destroyalAllWindows()
輸出結果
解說
匯入所有必要的模塊:。import cv2
import numpy as np
- 定義一個函式,
process(),接收一個BGR影像陣列作為其引數:
def process(img) 。
- 處理開始時,將影像轉換為灰度。然后我們將灰度陣列中小于
5的每一個值替換成一個更大的數字(我使用了255)。這樣做的原因是為了淡化影像的背景,這樣盒子的邊緣將更容易被發現: 。
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_gray[img_gray < 5] = 255。
- 我們現在可以使用canny邊緣檢測器來檢測盒子的邊緣。2 迭代擴張將很好地增強檢測到的邊緣。然后回傳擴張后的影像(二進制格式): 。
return cv2.dilate(cv2. Canny(img_gray, 50, 75), np.ones((4, 4) , iterations=2)
- 定義一個函式,
get_pts(),接收一個BGR影像陣列作為其引數:
def get_cnts(img)。
- 使用
cv2.findContours()方法,我們找到影像的輪廓(使用我們之前定義的process()函式處理),并回傳一個面積高于40000和低于80000的所有輪廓的串列。顯著不同的盒子尺寸將需要調整這些值: 。
cnts, _ = cv2.findContours(process(img), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
return [cnt for cnt in cnts if 80000 > cv2. contourArea(cnt) > 40000 ]
- 讀取影像檔案,獲得其輪廓,并使用
cv2.boundingRect()和cv2.rectangle()方法繪制每個輪廓的邊界矩形:
img = cv2.imread("image.png")
cnts = get_cnts(img)
for cnt in cnts:
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(img, (x, y), (x w, y h), (0, 255, 0), 3)
- 最后,為了裁剪影像,獲得串列中所有輪廓線組合的邊界矩形(可以通過用
np.concatenate()方法連接輪廓線來完成)并顯示結果:
x, y, w, h = cv2.boundingRect(np.concatenate(cnts))
cv2.imshow("Image", img[y: y h, x: x w] )
cv2.waitKey(0)
cv2.destroyalAllWindows()
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/328645.html
標籤:




