0

我是一個新手,以計算機視覺,我試圖檢測到這種圖像中的所有測試條:如何使用OpenCV檢測試紙?

source

結果我試圖得到:

result

我認爲它應該很容易,因爲所有的目標對象都是矩形的,並且具有固定的高寬比。但我不知道應該使用哪種算法或函數。

我已經嘗試過OpenCV中的邊緣檢測和2D特徵檢測示例,但結果並不理想。我應該如何檢測這些相似的物體,但差異很小?

更新:

測試條可以以顏色變化,並且當然,結果線的陰影。但是它們都具有相同的參考線,在畫面顯示:

variations of test strips

我不知道我應該怎麼形容這些簡單的功能爲目標檢測,因爲大多數的例子,我在網上找到的是複雜的對象像建築物或面部。

+1

只是一些sugestions,1)試圖消除背景(閾值)。 2)找線,也許[hough line transform](http://docs.opencv.org/2。4/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html)可以幫助,3)找到這些線的交點4)用這個交點創建矩形。獎金)您可以嘗試將每個物體(輪廓)與其餘物體(其餘物體=黑色)進行隔離,然後逐個分析它們,而沒有任何其他數據可能會影響結果 – api55

+0

您是否還有更多圖像可以查看其中的變化? –

+0

@MarkSetchell請參閱我的更新 – zhengyue

回答

2

解決方案並不確切,但它提供了一個很好的起點。儘管你必須使用參數。如果您使用某種閾值方法分割條,然後單獨應用@ api55提到的hough線,它將對您有很大的幫助。

這是我得到的結果。

after laplacianafter thresholding and median filteringfinal image

代碼。

import cv2 
import numpy as np 

# read image 
img = cv2.imread('KbxN6.jpg') 
# filter it 
img = cv2.GaussianBlur(img, (11, 11), 0) 
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 

# get edges using laplacian 
laplacian_val = cv2.Laplacian(gray_img, cv2.CV_32F) 

# lap_img = np.zeros_like(laplacian_val, dtype=np.float32) 
# cv2.normalize(laplacian_val, lap_img, 1, 255, cv2.NORM_MINMAX) 
# cv2.imwrite('laplacian_val.jpg', lap_img) 

# apply threshold to edges 
ret, laplacian_th = cv2.threshold(laplacian_val, thresh=2, maxval=255, type=cv2.THRESH_BINARY) 
# filter out salt and pepper noise 
laplacian_med = cv2.medianBlur(laplacian_th, 5) 
# cv2.imwrite('laplacian_blur.jpg', laplacian_med) 
laplacian_fin = np.array(laplacian_med, dtype=np.uint8) 

# get lines in the filtered laplacian using Hough lines 
lines = cv2.HoughLines(laplacian_fin,1,np.pi/180,480) 
for rho,theta in lines[0]: 
    a = np.cos(theta) 
    b = np.sin(theta) 
    x0 = a*rho 
    y0 = b*rho 
    x1 = int(x0 + 1000*(-b)) 
    y1 = int(y0 + 1000*(a)) 
    x2 = int(x0 - 1000*(-b)) 
    y2 = int(y0 - 1000*(a)) 
    # overlay line on original image 
    cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2) 

# cv2.imwrite('processed.jpg', img) 
# cv2.imshow('Window', img) 
# cv2.waitKey(0) 
+0

謝謝!我會試一試並更新結果。 – zhengyue

0

這是一個替代解決方案,它使用函數findCountours和canny邊緣檢測相結合。該代碼是基於非常輕微地這個tutorial

import cv2 
import numpy as np 
import imutils 

image = cv2.imread('test.jpg') 
resized = imutils.resize(image, width=300) 
ratio = image.shape[0]/float(resized.shape[0]) 

# convert the resized image to grayscale, blur it slightly, 
# and threshold it 
gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY) 
edges = cv2.Canny(resized,100,200) 
cv2.imshow('dsd2', edges) 
cv2.waitKey(0) 
cnts = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, 
    cv2.CHAIN_APPROX_NONE) 
cnts = cnts[0] if imutils.is_cv2() else cnts[1] 
sd = ShapeDetector() 

# loop over the contours 
for c in cnts: 
    # compute the center of the contour, then detect the name of the 
    # shape using only the contour 
    M = cv2.moments(c) 
    cX = int((M["m10"]/M["m00"]) * ratio) 
    cY = int((M["m01"]/M["m00"]) * ratio) 


    # multiply the contour (x, y)-coordinates by the resize ratio, 
    # then draw the contours and the name of the shape on the image 
    c = c.astype("float") 
    c *= ratio 
    c = c.astype("int") 
    cv2.drawContours(image, [c], -1, (0, 255, 0), 2) 
    #show the output image 
    #cv2.imshow("Image", image) 
    #cv2.waitKey(0) 
cv2.imwrite("erg.jpg",image) 

結果: enter image description here


我想它可以通過調整下列參數進行改進:

它也許也有用過濾小輪廓或合併輪廓它們彼此接近。