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


我想它可以通过调整下列参数进行改进:

它也许也有用过滤小轮廓或合并轮廓它们彼此接近。