首页 > 解决方案 > 带有轮廓的扑克牌的 4 个角

问题描述

我试图找到一张扑克牌的 4 个角的坐标,这样我就可以用它来扭曲卡片的透视图,然后再用于识别。我曾尝试使用 cv.boundingRect,但由于我使用的是实时视频源,我只需要卡片,而不需要卡片最近的矩形。现在它使用boundingRect工作,但如果我倾斜图像的角度,坐标是boundingRect而不是扑克牌。见图片: 直角 ... 弯角

然后我需要我的轮廓坐标用于扑克牌的 4 个角,而不是使用 boundingRect。到目前为止,这是我的方法:

def getContours(img, imgContour, standardimg):
global counter
contours, hierachy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

for contour in contours:
    area = cv2.contourArea(contour)
    areaMin = cv2.getTrackbarPos("area", "parameters")
    if area > areaMin:
        cv2.drawContours(imgContour, contour, -1, (255, 0, 255), 5)
        peri = cv2.arcLength(contour, True)
        approx = cv2.approxPolyDP(contour, 0.04 * peri, True)

        if len(approx) == 4:
            x, y, w, h = cv2.boundingRect(approx)

            cv2.rectangle(imgContour, (x, y), (x + w, y + h), (255, 255, 0), 3)


            cv2.putText(imgContour, "Area: " + str(int(area)), (x + w + 20, y + 45), cv2.FONT_HERSHEY_COMPLEX, 0.7,
                        (0, 255, 0), 2)

            if cv2.waitKey(1) & 0xFF == ord('c'):
                counter = counter + 1
                cv2.imwrite('warpedPicture' + str(counter) + '.jpg', imgContour)

                coordinates.insert(0, x)
                coordinates.insert(1, y)
                coordinates.insert(2, h)
                coordinates.insert(3, w)
                warpPicture(coordinates[0], coordinates[1], coordinates[2], coordinates[3], standardimg)

标签: pythonopencvopencv-contour

解决方案


Python/OpenCV 中一种可能比边界框更好的方法如下:

  • 读取输入
  • 转换为灰色
  • 临界点
  • 获取外部轮廓
  • 计算周长
  • 将轮廓近似为四边形
  • 在输入上绘制四边形
  • 保存结果


输入 A:

在此处输入图像描述

import cv2
import numpy as np

# load image
img = cv2.imread("5_hearts_A.png")
hh, ww = img.shape[:2]

# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold the grayscale image
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]

# remove white borders
thresh = thresh[2:hh-2, 2:ww-2]
thresh = cv2.copyMakeBorder(thresh, 2,2,2,2, cv2.BORDER_REPLICATE)

# find outer contour
cntrs = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]
cntr = cntrs[0]

# draw contour on copy of img as result
contour = img.copy()
cv2.drawContours(contour,[cntr], 0, (0,0,255), 1)

# limit contour to quadrilateral
peri = cv2.arcLength(cntr, True)
corners = cv2.approxPolyDP(cntr, 0.04 * peri, True)

# draw quadrilateral on input image from detected corners
result = img.copy()
cv2.polylines(result, [corners], True, (0,0,255), 1, cv2.LINE_AA)

# write result to disk
cv2.imwrite("5_hearts_A_contour.png", contour)
cv2.imwrite("5_hearts_A_quadrilateral.png", result)

# display results
cv2.imshow("THRESH", thresh)
cv2.imshow("CONTOUR", contour)
cv2.imshow("QUAD", result)
cv2.waitKey(0)
cv2.destroyAllWindows()


轮廓图:

在此处输入图像描述

产生的四边形:

在此处输入图像描述

对于图像 B 类似:

在此处输入图像描述

图像 B 的轮廓:

在此处输入图像描述

图像 B 的结果:

在此处输入图像描述

一种可能会做得更好的方法是对阈值图像进行 Canny 边缘检测。然后霍夫线变换。然后计算线的交点以找到拐角。


推荐阅读