Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在圆内寻找轮廓_Python_Opencv_Contour - Fatal编程技术网

Python 在圆内寻找轮廓

Python 在圆内寻找轮廓,python,opencv,contour,Python,Opencv,Contour,我正在尝试编写一个程序,可以检测圆形透镜上的直线切割,如图像左侧所示: 现在,我已经尝试使用Canny边缘检测、Hough线变换和findContour来单独分离线,但没有成功 我还尝试通过首先检测镜头的外圆并在ROI(检测到的圆)内执行轮廓搜索来检测线条,但我得到的是镜头上的随机线条,而不是我想要的输出 首先,我想指出你的图像非常嘈杂。这意味着仅仅通过寻找轮廓、边缘或线条可能不会起作用,因为这是由于噪音造成的。这使得任务非常困难。如果你正在寻找一种方法来自动化这样一项任务,我建议你努力寻找合

我正在尝试编写一个程序,可以检测圆形透镜上的直线切割,如图像左侧所示:

现在,我已经尝试使用Canny边缘检测、Hough线变换和findContour来单独分离线,但没有成功


我还尝试通过首先检测镜头的外圆并在ROI(检测到的圆)内执行轮廓搜索来检测线条,但我得到的是镜头上的随机线条,而不是我想要的输出

首先,我想指出你的图像非常嘈杂。这意味着仅仅通过寻找轮廓、边缘或线条可能不会起作用,因为这是由于噪音造成的。这使得任务非常困难。如果你正在寻找一种方法来自动化这样一项任务,我建议你努力寻找合适的照明(我认为一个经典的顶灯就足够了),因为它会在图像上产生更少的噪音(更少的反射…),因此更容易做出这样的算法

话虽如此。我举了一个例子,说明我将如何努力完成这项任务。请注意,此解决方案可能不适用于其他图像,但在这个示例中,结果非常好。它可能会给你一个新的观点来解决这个问题

首先,我将尝试在使用大津阈值将图像转换为二进制之前执行直方图均衡化。之后,我将在图像上执行打开(先腐蚀,然后膨胀):

之后,我会在最大的轮廓上做一个边界框。通过x,y,h,w,我可以计算边界框的中心,它将作为我要创建的ROI的中心。在图像副本上绘制半径略小于w/2的圆,在新遮罩上绘制半径等于w/2的圆。然后执行按位操作:

现在您有了ROI,必须再次设置阈值,以使边界无噪声并搜索轮廓:

现在您可以看到有两个轮廓(内部和外部)。现在你可以提取镜头被切割的区域。可以通过计算内轮廓和外轮廓的每个点之间的距离来实现这一点。两点之间距离的公式为
sqrt((x2-x1)^2+(y2-y2)^2)
。设置此距离的阈值,以便在距离小于某个整数时,在图像上的这两个点之间绘制一条线。我用一条蓝线画出了距离。之后,将图像转换为HSV颜色空间,并再次使用逐位操作对其进行遮罩,以便只剩下那些蓝线:

再次执行OTSU阈值,选择最大轮廓(那些蓝线),并通过轮廓拟合一条线。在原始图像上画一条线,您将得到最终结果:

示例代码:

import cv2
import numpy as np

### Perform histogram equalization and threshold with OTSU.
img = cv2.imread('lens.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
equ = cv2.equalizeHist(gray)
_, thresh = cv2.threshold(equ,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

### Perform opening (erosion followed by dilation) and search for contours.
kernel = np.ones((2,2),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)
_, contours, hierarchy = cv2.findContours(opening,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

### Select the biggest one and create a bounding box.
### This will be used to calculate the center of your ROI.
cnt = max(contours, key=cv2.contourArea)

### Calculate x and y of the center.
x,y,w2,h2 = cv2.boundingRect(cnt)
center_x = int(x+(w2/2))
center_y = int(y+(h2/2))

### Create the radius of your inner circle ROI and draw it on a copy of the image.
img2 = img.copy()
radius = int((w2/2)-20)
cv2.circle(img2,(center_x,center_y), radius, (0,0,0), -1)

### Create the radius of your inner circle ROI and draw it on a blank mask.
radius_2 = int(w2/2)
h,w = img.shape[:2]
mask = np.zeros((h, w), np.uint8)
cv2.circle(mask,(center_x,center_y), radius_2, (255,255,255), -1)

### Perform a bitwise operation so that you will get your ROI
res = cv2.bitwise_and(img2, img2, mask=mask)

### Modify the image a bit to eliminate noise with thresholding and closing.
_, thresh = cv2.threshold(res,190,255,cv2.THRESH_BINARY)
kernel = np.ones((3,3),np.uint8)
closing = cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,kernel, iterations = 2)

### Search for contours again and select two biggest one.
gray = cv2.cvtColor(closing,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
area = sorted(contours, key=cv2.contourArea, reverse=True)
contour1 = area[0]
contour2 = area[1]

### Iterate through both contours and calculate the minimum distance.
### If it is less than the threshold you provide, draw the lines on the image.
### Forumula is sqrt((x2-x1)^2 + (y2-y2)^2).
for i in contour1:
    x = i[0][0]
    y = i[0][1]
    for j in contour2:
        x2 = j[0][0]
        y2 = j[0][1]
        dist = np.sqrt((x2-x)**2 + (y2-y)**2)
        if dist < 12:
            xy = (x,y)
            x2y2 = (x2,y2)
            line = (xy,x2y2)
            cv2.line(img2,xy,x2y2,(255,0,0),2)
        else:
            pass

### Transform the image to HSV colorspace and mask the result.
hsv = cv2.cvtColor(img2, cv2.COLOR_BGR2HSV)
lower_blue = np.array([110,50,50])
upper_blue = np.array([130,255,255])
mask = cv2.inRange(hsv, lower_blue, upper_blue)
res = cv2.bitwise_and(img2,img2, mask= mask)

### Search fot contours again.
gray = cv2.cvtColor(res,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)

### Fit a line through the contour and draw it on the original image.
[vx,vy,x,y] = cv2.fitLine(cnt, cv2.DIST_L2,0,0.01,0.01)
left = int((-x*vy/vx) + y)
right = int(((w-x)*vy/vx)+y)
cv2.line(img,(w-1,right),(0,left),(0,0,255),2)

### Display the result.
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
导入cv2
将numpy作为np导入
###使用OTSU执行直方图均衡化和阈值。
img=cv2.imread('lens.jpg')
灰色=cv2.CVT颜色(img,cv2.COLOR\U BGR2GRAY)
equ=cv2.均衡历史(灰色)
_,thresh=cv2.阈值(equ,0255,cv2.thresh_BINARY+cv2.thresh_OTSU)
###执行打开(腐蚀后膨胀)并搜索轮廓。
内核=np.ones((2,2),np.uint8)
opening=cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel,迭代次数=2)
_,等高线,层次=cv2.findContours(开口,cv2.RETR\u树,cv2.CHAIN\u近似值\u无)
###选择最大的一个并创建一个边界框。
###这将用于计算投资回报率的中心。
cnt=最大值(轮廓,关键点=cv2.轮廓面积)
###计算中心的x和y。
x、 y,w2,h2=cv2.boundingRect(cnt)
中心x=int(x+(w2/2))
中心y=int(y+(h2/2))
###创建内圈ROI的半径,并将其绘制在图像副本上。
img2=img.copy()
半径=整数((w2/2)-20)
cv2.圆(img2,(中心x,中心y),半径,(0,0,0),-1)
###创建内圈ROI的半径,并将其绘制在空白遮罩上。
半径_2=int(w2/2)
h、 w=图像形状[:2]
掩码=np.0((h,w),np.uint8)
cv2.圆(遮罩,(中心x,中心y),半径2,(255255),-1)
###执行逐位操作,以便获得ROI
res=cv2.按位_和(img2,img2,mask=mask)
###稍微修改图像以通过阈值和关闭消除噪声。
_,thresh=cv2.threshold(res,190255,cv2.thresh\u二进制)
内核=np.ones((3,3),np.uint8)
closing=cv2.morphologyEx(thresh,cv2.MORPH\u CLOSE,kernel,迭代次数=2)
###再次搜索等高线并选择两个最大的等高线。
灰色=cv2.CVT颜色(闭合,cv2.COLOR\u BGR2GRAY)
_,thresh=cv2.阈值(灰色,0255,cv2.thresh_二进制+cv2.thresh_大津)
_,等高线,层次=cv2.查找到的轮廓(阈值,cv2.检索树,cv2.链约无)
面积=已排序(等高线,关键点=cv2.contourArea,反向=真)
轮廓线1=面积[0]
轮廓2=面积[1]
###迭代两条等高线并计算最小距离。
###如果小于您提供的阈值,请在图像上绘制线条。
###Forumula是sqrt((x2-x1)^2+(y2-y2)^2)。
对于轮廓图1中的i:
x=i[0][0]
y=i[0][1]
对于轮廓图2中的j:
x2=j[0][0]
y2=j[0][1]
距离=np.sqrt((x2-x)**2+(y2-y)**2)
如果距离<12:
xy=(x,y)
x2y2=(x2,y2)
直线=(xy,x2y2)
cv2.线(img2,xy,x2y2,(255,0,0),2)
其他:
通过
###将图像转换为HSV颜色空间并遮罩结果。
hsv=cv2.CVT颜色(img2,cv2.COLOR_BGR2HSV)
lower_blue=np.数组([110,50,50])
上_蓝=np.数组([130255255])
遮罩=cv2.inRange(hsv、下蓝、上蓝)
res=cv2.按位_和(img2,img2,mask=mask)
###再次搜索轮廓。
灰色=cv2.CVT颜色(分辨率,cv2.COLOR\u BGR2GRAY)
_,thresh=cv2.阈值(灰色,0255,cv2.thresh_二进制+cv2.thresh_大津)
_,等高线,层次=cv2.查找到的轮廓(阈值,cv2.检索树,cv2.链约无)
cnt=最大值(轮廓,关键点=cv2.轮廓面积)
###通过轮廓拟合一条线并在原始图像上绘制。
[vx,vy,x,y]=cv2.fitLine(cnt,cv2.D