opencv 获取矩形轮廓的坐标

4dc9hkyq  于 2023-08-06  发布在  其他
关注(0)|答案(2)|浏览(106)

我试图得到一个图像中的矩形的4个点。我有代码,得到的图像的轮廓,并检测它是否有4点。但我不知道如何从等高线数据中得到这4个点。这是我目前所知道的。它来自我从各种图像处理教程中找到的代码。

import cv2
import numpy as np

green = (0, 255, 0)  # for drawing contours, etc.

# a normal video capture loop
cap = cv2.VideoCapture(1)
if not cap.isOpened():
    print("Cannot open camera")
    exit()

while True:
    ret, frame = cap.read()
    if not ret:
        print("Can't receive frame (stream end?). Exiting ...")
        break

    image = frame.copy()  # can tweak this one
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (5, 5), 0)
    edged = cv2.Canny(blur, 75, 200)

    contours, _ = cv2.findContours(edged, cv2.RETR_LIST, 
                                   cv2.CHAIN_APPROX_SIMPLE)
    contours = sorted(contours, key=cv2.contourArea, reverse=True)
    cv2.drawContours(image, contours, -1, green, 3)

    # go through each contour looking for the one with 4 points
    # This is a rectangle, and the first one will be the biggest because
    # we sorted the contours from largest to smallest
    doc_cnts = None
    if len(contours) >= 1:
        for contour in contours:
            # we approximate the contour
            peri = cv2.arcLength(contour, True)
            approx = cv2.approxPolyDP(contour, 0.05 * peri, True)
            if len(approx) == 4:
                doc_cnts = approx
                break

    if doc_cnts is not None:
        print(doc_cnts)

    cv2.imshow('original', frame)
    cv2.imshow('changed', edged)

    if cv2.waitKey(1) == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

字符串
当我运行这个时,边缘图像看起来像是在图像中找到了一些矩形的东西。我把相机对准地板上的一个信封。我看到很多小的背景边缘,从地毯图案,我确实看到了较大的矩形一个信封。
我不理解矩形的实际轮廓数据的格式,也不知道如何使用它来获得实际的x,y坐标。我不只是想画轮廓,我想测试矩形,以确保图像是采取正面。

oug3syen

oug3syen1#

以下是在Python/OpenCV中打印矩形轮廓顶点的两种简单方法
输入:
x1c 0d1x的数据

import cv2
import numpy as np

# read the image of rectangle as grayscale
img = cv2.imread('rect.png', cv2.IMREAD_GRAYSCALE)

# threshold
thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]

# compute largest contour
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)

# Reduce vertices
peri = cv2.arcLength(big_contour, True)
approx = cv2.approxPolyDP(big_contour, 0.001 * peri, True)

# print approx
print(approx)

print('')

# print coordinates in approx
for p in approx:
    x = p[0][0]
    y = p[0][1]
    pt = str(x) + "," + str(y)
    print(pt)

字符串
打印结果(大约):

[[[100 100]]

 [[100 400]]

 [[400 400]]

 [[400 100]]]


x,y坐标打印列表的结果:

100,100
100,400
400,400
400,100

uqzxnwby

uqzxnwby2#

我找到了一些有用的代码。我可以得到矩形形状的4个点,这样做:

blur = cv2.morphologyEx(frame, cv2.MORPH_CLOSE, blur_kernel, iterations= 3)

    edged = cv2.Canny(blur, 75, 200)  # original is 75, 200

    contours, _ = cv2.findContours(edged, cv2.RETR_LIST,  # was RETR_TREE
                                   cv2.CHAIN_APPROX_SIMPLE)
    contours = sorted(contours, key=cv2.contourArea, reverse=True)

    # go through each contour looking for the one with 4 points
    # This is a rectangle, and the first one will be the biggest because
    # we sorted the contours from largest to smallest
    doc_cnts = None
    if len(contours) >= 1:
        for contour in contours:
            # we approximate the contour
            peri = cv2.arcLength(contour, True)
            approx = cv2.approxPolyDP(contour, 0.05 * peri, True)
            if len(approx) == 4:
                # cv2.drawContours(image, [approx], 0, green, 2)
                all_coordinates = approx.ravel()
                x1 = all_coordinates[0]
                y1 = all_coordinates[1]
                x2 = all_coordinates[2]
                y2 = all_coordinates[3]
                x3 = all_coordinates[4]
                y3 = all_coordinates[5]
                x4 = all_coordinates[6]
                y4 = all_coordinates[7]

                # get the total length of this rectangle

                string = str(x1) + " " + str(y1)
                cv2.putText(frame, string, (x1, y1),
                            cv2.FONT_HERSHEY_COMPLEX, 0.5, green)
                string = str(x2) + " " + str(y2)
                cv2.putText(frame, string, (x2, y2),
                            cv2.FONT_HERSHEY_COMPLEX, 0.5, green)
                string = str(x3) + " " + str(y3)
                cv2.putText(frame, string, (x3, y3),
                            cv2.FONT_HERSHEY_COMPLEX, 0.5, green)
                string = str(x4) + " " + str(y4)
                cv2.putText(frame, string, (x4, y4),
                            cv2.FONT_HERSHEY_COMPLEX, 0.5, green)

                cv2.line(frame, color=green,
                        pt1=(x1, y1),
                        pt2=(x2, y2),
                        thickness=5)
                cv2.line(frame, color=green,
                        pt1=(x2, y2),
                        pt2=(x3, y3),
                        thickness=5)
                cv2.line(frame, color=green,
                        pt1=(x3, y3),
                        pt2=(x4, y4),
                        thickness=5)
                cv2.line(frame, color=green,
                        pt1=(x4, y4),
                        pt2=(x1, y1),
                        thickness=5)

                break

字符串
这只是一个讨厌的测试代码,但我想确保我可以得到一个4边形状的坐标。它似乎工作,但它有时拿起奇怪的轮廓上的图像,并给出奇怪的结果。我想我有足够的时间来玩它,得到一些更稳定的东西。

相关问题