首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenCV -如何找到圆角矩形的矩形轮廓?

问OpenCV -如何找到圆角矩形的矩形轮廓?
EN

Stack Overflow用户
提问于 2017-09-29 17:39:45
回答 3查看 38.8K关注 0票数 16

我正在尝试寻找图像中一个圆角矩形物体的轮廓。我尝试了HoughLinesP和findContours,但没有达到预期的效果。

​

​

我想像这样找到这个矩形:

​

代码:

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt
import util

image = cv2.imread("./img/findrect0.png", 1)
gray = util.grayImage(image)

edges = cv2.Canny(image, 50, 200)
lines = cv2.HoughLinesP(edges, 1, cv2.cv.CV_PI/180, 50, minLineLength=50, maxLineGap=10)[0]
linesImage = image.copy()
util.drawLines(linesImage, lines, thickness=10)

contoursImage = image.copy()
(contours, hierarchy) = cv2.findContours(gray.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

util.drawContours(contoursImage, contours, thickness=10)

util.showOpenCVImagesGrid([image, edges, linesImage, contoursImage], 2, 2, titles=["original image", "canny image", "lines image", "contours image"])

util:

代码语言:javascript
复制
import cv2
import math
import matplotlib.pyplot as plt

def showOpenCVImagesGrid(images, x, y, titles=None, axis="on"):
    fig = plt.figure()
    i = 1
    for image in images:
        copy = image.copy()
        channel = len(copy.shape)
        cmap = None
        if channel == 2:
            cmap = "gray"
        elif channel == 3:
            copy = cv2.cvtColor(copy, cv2.COLOR_BGR2RGB)
        elif channel == 4:
            copy = cv2.cvtColor(copy, cv2.COLOR_BGRA2RGBA)

        fig.add_subplot(x, y, i)
        if titles is not None:
            plt.title(titles[i-1])
        plt.axis(axis)
        plt.imshow(copy, cmap=cmap)
        i += 1
    plt.show()


def grayImage(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    return gray


def drawLines(image, lines, thickness=1):
    for line in lines:
        # print("line="+str(line))
        cv2.line(image, (line[0], line[1]), (line[2], line[3]),
                (0, 0, 255), thickness)


def drawContours(image, contours, thickness=1):
    i = 0
    for contour in contours:
        cv2.drawContours(image, [contours[i]], i, (0, 255, 0), thickness)
        area = cv2.contourArea(contour)
        i += 1

我使用的是Python 2.7.13和OpenCV 2.4.13.3。

我一直在考虑延伸这些线,并得到线的交点。最后,我将得到矩形的四个坐标。但如果图像更复杂,我不知道如何处理。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-09-29 17:53:15

您需要找到找到的等高线的边界矩形。

代码语言:javascript
复制
img = cv2.imread("image.png", -1)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

binary = cv2.bitwise_not(gray)

(_,contours,_) = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

for contour in contours:
    (x,y,w,h) = cv2.boundingRect(contour)
    cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)

​

​

票数 23
EN

Stack Overflow用户

发布于 2017-09-29 18:07:31

您可以找到非零点的边界矩形。

代码语言:javascript
复制
image = cv2.imread("./img/findrect0.png", 1)
gray = util.grayImage(image)
gray_inv = cv2.bitwise_not(gray)
points = cv2.findNonZero(gray)
rect = cv2.boundingRect(points)
票数 3
EN

Stack Overflow用户

发布于 2017-09-29 18:10:07

我一直在考虑延伸这些直线,得到直线的交点。,

。最后,我将得到矩形的四个坐标。

或多或少,如果轮廓对你不起作用,这是一个很好的方法。确实,正如你所说,

但如果图像更复杂,我不知道如何处理。

有一些复杂的问题需要处理。主要的问题是,典型的直线检测并不是每次都能给你完美的线段。沿同一条直线可以有多个直线段,可以是纵向堆叠的,也可以是多个重叠的。此外,您还需要以某种方式自动分割直线,这样您就不会试图找到平行线的交点。

然而,这两个问题都不是很难处理。我answered a question awhile ago on this site关于从HoughLinesP中寻找交叉点,它使用了很多下面的建议,尽管不是那么健壮(例如,将线分割成两组,这样做要天真得多),但它应该会给你一个很好的起点。

检测到线后,需要将线分段为组或平行线段。如果您的矩形具有定义的方向,那么您可以根据该方向过滤直线,这将是最简单的情况。但是,如果矩形可以是任意方向的,则需要使用其他方法对其进行分割。您可以使用k-means聚类和k=2来找到两个主要角度,并将一个角度对应的直线放在一个bin中,将另一个角度对应的直线放在另一个bin中,并找到一个bin中的线与另一个bin中的线的交点。这种方法的好处是,它可以适用于任何平行四边形。如果线不在某个阈值内(例如10度或更高),则也可以拒绝来自每个箱的线,使其与另一个箱的平均角度成直角,或者如果你想坚持矩形。

一旦你有了所有的线相应的二进制,你可以计算它们的交点。实际上,有一个a nice formula using determinants用于计算两条直线之间的交点,给定直线上的两个点,您已经从端点获得了这些点。所以,这很方便!bin 0中的每条线都将与bin 1中的线有一个交点,这就是您需要做的全部工作。

所以在这里的最后,你会有4个交叉点的集群。一种选择是简单地将这些分组在一起,同样使用k-means和k=4,您将拥有这四个点群集的质心,代表您的矩形的角点。当然,由于您在此过程中使用了很多近似步骤,因此您的点不会精确地定义一个矩形,因此您必须尽可能地拟合与这些点最接近的矩形。或者,代替k-means,另一种方法是尝试找到许多交叉点中最准确地表示矩形的子集,然后拟合最接近的矩形。也许可以使用线性回归、最小二乘、RANSAC等方法来解决这个问题。或者,如果您愿意,也可以使用boundingRect()找到这四个点的边界矩形。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46486078

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档