如何从python中的模糊图像中找到变形矩形的准确角位置?

我正在寻找一种使用Python中的OpenCV准确检测变形矩形的角的过程。

我已经通过谷歌搜索尝试了不同建议的解决方案,但是通过直线的正弦叠加(请参见阈值图像),我可能无法检测到拐角。到目前为止,我尝试过findContours和HoughLines,但效果不佳。 不幸的是,我不理解how to find blur corner position with opencv?

中来自徐斌的C代码

这是我的初始图片:

如何从python中的模糊图像中找到变形矩形的准确角位置?

调整大小和阈值后,我应用canny边缘检测来获取以下图像:

如何从python中的模糊图像中找到变形矩形的准确角位置?

contours,hierarchy = cv2.findContours(g_mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
box = cv2.minAreaRect(contour)
box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
box = np.array(box,dtype="float")
box = perspective.order_points(box)

我只能通过一些额外的绘图获得以下结果:

如何从python中的模糊图像中找到变形矩形的准确角位置?

我认为进行线路拟合将是解决问题的好方法,但不幸的是,我无法使HoughLines正常工作,并且在查看OpenCV Python - How to implement RANSAC to detect straight lines?后,RANSAC似乎也很难解决我的问题。

我们非常感谢您的帮助。

lcmoba72 回答:如何从python中的模糊图像中找到变形矩形的准确角位置?

虽然这是旧的,但这至少可以帮助任何其他有同样问题的人。除了 nathancy 的答案之外,这应该可以让您更准确地找到非常模糊的角落:

伪代码

  1. 根据需要调整大小,但没有必要
  2. 转换为灰度
  3. 应用模糊或双边过滤
  4. 应用 Otsu 阈值获得二值图像
  5. 找出构成矩形的轮廓
  6. 将轮廓近似为矩形
  7. 近似点是矩形的角!

执行此操作的代码

  1. 调整大小:
    该函数采用新的宽度和高度,因此我只是将图像制作为当前尺寸的 5 倍。
img = cv2.resize(img,(img.shape[0] * 5,img.shape[1] * 5))

resized

  1. 灰度转换:
    只是从 OpenCV 的默认 BGR 色彩空间转换为灰度。
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

gray

  1. 模糊/双边过滤:
    如果需要,您可以使用任意数量的技术进一步柔化此图像。也许是高斯模糊,或者如 nathancy 建议的那样,是双边滤波器,但两者都不需要。
# choose one,or a different function
blurred = cv2.GaussianBlur(gray,(5,5),0)
blurred = cv2.bilateralFilter(gray,9,75,75)

blurred

  1. 大津的门槛
    使用阈值函数,传递 0255 作为阈值和最大值的参数。我们传入 0 是因为我们使用了阈值技术 cv2.THRESH_OTSU,它为我们确定了值。这与阈值本身一起返回,但我只是将其设置为 _,因为我们不需要它。
_,thresh = cv2.threshold(blurred,255,cv2.THRESH_OTSU)

thresh

  1. 寻找轮廓
    轮廓的内容比我在这里解释的要多得多,请随时查看 docs。 对我们来说重要的事情是它返回一个轮廓列表和一个层次结构。我们不需要层次结构所以它被设置为 _,我们只需要它找到的单个轮廓,所以我们设置 contour = contours[0]
contours,_ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
contour = contours[0]

contour

  1. 近似轮廓为矩形
    首先我们计算轮廓的周长。然后我们用cv2.approxPolyDP函数对其进行近似,并用0.05 * perimeter告诉它原始曲线与其近似值之间的最大距离。您可能需要使用小数点以获得更好的近似值。
    approx 是一个形状为 (num_points,1,2) 的 numpy 数组,在本例中为 (4,2),因为它找到了矩形的 4 个角。

请在docs中阅读更多内容。

perimeter = cv2.arcLength(contour,True)
approx = cv2.approxPolyDP(contour,0.05 * perimeter,True)
  1. 找到你的倾斜矩形!
    你已经完成了!这就是你如何绘制这些点。首先,我们通过循环绘制圆圈,然后获取 x 和 y 坐标,然后绘制矩形本身。
# drawing points
for point in approx:
    x,y = point[0]
    cv2.circle(img,(x,y),3,(0,0),-1)

# drawing skewed rectangle
cv2.drawContours(img,[approx],-1,0))

finished product

完成代码

import cv2

img = cv2.imread("rect.png")

img = cv2.resize(img,img.shape[1] * 5))
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
blurred = cv2.bilateralFilter(gray,75)
_,cv2.THRESH_OTSU)

contours,cv2.CHAIN_APPROX_SIMPLE)
contour = contours[0]

perimeter = cv2.arcLength(contour,True)

for point in approx:
    x,-1)
cv2.drawContours(img,0))
,

要检测拐角,可以使用cv2.goodFeaturesToTrack()。该函数有四个参数

corners = cv2.goodFeaturesToTrack(image,maxCorners,qualityLevel,minDistance)
  • image-输入8位或浮点32位灰度单通道图像
  • maxCorners-要返回的最大拐角数
  • qualityLevel-0-1之间的最小可接受角点质量等级。低于质量级别的所有角落
  • minDistance-拐角之间的最小欧几里得距离

现在我们知道如何找到角,我们必须找到旋转的矩形并应用该函数。这是一种方法:


我们首先放大图像,转换为灰度,应用双边滤镜,然后使用Otsu的阈值获得二进制图像

接下来,我们通过使用cv2.findContours()查找轮廓来找到变形的矩形,然后获得以绿色突出显示的旋转边界框。我们将边界框绘制到蒙版上

现在有了遮罩,我们只需使用cv2.goodFeaturesToTrack()在遮罩上找到角点

这是原始输入图像上的结果以及每个角的(x,y)坐标

角点

(377.0,375.0)
(81.0,344.0)
(400.0,158.0)
(104.0,127.0)

代码

import cv2
import numpy as np
import imutils

# Resize image,blur,and Otsu's threshold
image = cv2.imread('1.png')
resize = imutils.resize(image,width=500)
mask = np.zeros(resize.shape,dtype=np.uint8)
gray = cv2.cvtColor(resize,cv2.COLOR_BGR2GRAY)
blur = cv2.bilateralFilter(gray,75)
thresh = cv2.threshold(blur,cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Find distorted rectangle contour and draw onto a mask
cnts = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
rect = cv2.minAreaRect(cnts[0])
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(resize,[box],(36,12),2)
cv2.fillPoly(mask,(255,255))

# Find corners on the mask
mask = cv2.cvtColor(mask,cv2.COLOR_BGR2GRAY)
corners = cv2.goodFeaturesToTrack(mask,maxCorners=4,qualityLevel=0.5,minDistance=150)

for corner in corners:
    x,y = corner.ravel()
    cv2.circle(resize,8,(155,20,255),-1)
    print("({},{})".format(x,y))

cv2.imshow('resize',resize)
cv2.imshow('thresh',thresh)
cv2.imshow('mask',mask)
cv2.waitKey()
本文链接:https://www.f2er.com/3149565.html

大家都在问