我正在尝试获取图像中矩形的 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 坐标。我不仅仅是想绘制轮廓,我想测试矩形以确保图像是正面拍摄的。
我找到了一些有帮助的代码。这样做我可以得到矩形的 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 边形状的坐标。它似乎有效,但有时它会在图像上拾取奇怪的轮廓并给出奇怪的结果。我想我有足够的时间去尝试它并获得更稳定的东西。
这里有两种在Python/OpenCV中打印矩形轮廓顶点的简单方法
输入:
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