简体   繁体   English

如何使用 python opencv 将重叠的卡彼此分开?

[英]How do i separate overlapping cards from each other using python opencv?

I am trying to detect playing cards and transform them to get a bird's eye view of the card using python opencv.我正在尝试检测扑克牌并将它们转换为使用 python opencv 鸟瞰卡片。 My code works fine for simple cases but I didn't stop at the simple cases and want to try out more complex ones.我的代码适用于简单的案例,但我并没有停留在简单的案例上,而是想尝试更复杂的案例。 I'm having problems finding correct contours for cards.Here's an attached image where I am trying to detect cards and draw contours:我在为卡片找到正确的轮廓时遇到问题。这是我试图检测卡片并绘制轮廓的附加图像:

在此处输入图像描述

My Code:我的代码:

path1 = "F:\\ComputerVisionPrograms\\images\\cards4.jpeg"
g = cv2.imread(path1,0)
img = cv2.imread(path1)

edge = cv2.Canny(g,50,200)

p,c,h = cv2.findContours(edge, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
rect = []
for i in c:
    p = cv2.arcLength(i, True)
    ap = cv2.approxPolyDP(i, 0.02 * p, True)
    if len(ap)==4:
        rect.append(i)
cv2.drawContours(img,rect, -1, (0, 255, 0), 3)

plt.imshow(img)
plt.show()

Result:结果:

在此处输入图像描述

This is not what I wanted, I wanted only the rectangular cards to be selected but since they are occluding one another, I am not getting what I expected.这不是我想要的,我只想选择矩形卡,但由于它们相互遮挡,我没有得到我期望的结果。 I believe I need to apply morphological tricks or other operations to maybe separate them or make the edges more prominent or may be something else.我相信我需要应用形态学技巧或其他操作来将它们分开或使边缘更加突出或可能是其他东西。 It would be really appreciated if you could share your approach to tackle this problem.如果您能分享您解决此问题的方法,将不胜感激。

A few more examples requested by other fellows:其他研究员要求的更多示例:

在此处输入图像描述

在此处输入图像描述

There are lots of approaches to find overlapping objects in the image.有很多方法可以在图像中找到重叠的对象。 The information you have for sure is that your cards are all rectangles, mostly white and have the same size.您确定的信息是您的卡片都是矩形,大部分是白色并且大小相同。 Your variables are brightness, angle, may be some perspective distortion.你的变量是亮度,角度,可能是一些透视失真。 If you want a robust solution, you need to address all that issues.如果您想要一个强大的解决方案,您需要解决所有这些问题。

I suggest using Hough transform to find card edges.我建议使用霍夫变换来查找卡片边缘。 First, run a regular edge detection.首先,运行常规边缘检测。 Than you need to clean up the results, as many short edges will belong to "face" cards.比你需要清理的结果,因为许多短边将属于“面”卡。 I suggest using a combination of dilate(11)->erode(15)->dilate(5).我建议使用 dilate(11)->erode(15)->dilate(5) 的组合。 This combination will fill all the gaps in the "face" card, then it "shrinks" down the blobs, on the way removing the original edges and finally grow back and overlap a little the original face picture.这种组合将填补“人脸”卡片中的所有空白,然后它“缩小”斑点,在去除原始边缘的过程中,最后长回来并与原始人脸图片重叠一点。 Then you remove it from the original image.然后将其从原始图像中删除。

Now you have an image that have almost all the relevant edges.现在你有一个几乎所有相关边缘的图像。 Find them using Hough transform.使用霍夫变换找到它们。 It will give you a set of lines.它会给你一组线。 After filtering them a little you can fit those edges to rectangular shape of the cards.在对它们进行一点过滤后,您可以将这些边缘适合卡片的矩形形状。

dst = cv2.Canny(img, 250, 50, None, 3)

cn = cv2.dilate(dst, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11)))
cn = cv2.erode(cn, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15, 15)))
cn = cv2.dilate(cn, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)))
dst -= cn
dst[dst < 127] = 0

cv2.imshow("erode-dilated", dst)

# Copy edges to the images that will display the results in BGR
cdstP = cv2.cvtColor(dst, cv2.COLOR_GRAY2BGR)

linesP = cv2.HoughLinesP(dst, 0.7, np.pi / 720, 30, None, 20, 15)

if linesP is not None:
    for i in range(0, len(linesP)):
        l = linesP[i][0]
        cv2.line(cdstP, (l[0], l[1]), (l[2], l[3]), (0, 255, 0), 2, cv2.LINE_AA)

cv2.imshow("Detected edges", cdstP)

This will give you following:这将为您提供以下信息:

在此处输入图像描述

Another way to get better results is to drop the edge detection/line detection part (I personally prefer) and find contours after image pre-processing.另一种获得更好结果的方法是放弃边缘检测/线检测部分(我个人更喜欢),在图像预处理后找到轮廓。

Below is my code and results:以下是我的代码和结果:

img = cv2.imread(<image_name_here>)
imgC = img.copy()

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

# Applying Otsu's thresholding
Retval, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# Finding contours with RETR_EXTERNAL flag to get only the outer contours
# (Stuff inside the cards will not be detected now.)
cont, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# Creating a new binary image of the same size and drawing contours found with thickness -1.
# This will colour the contours with white thus getting the outer portion of the cards.
newthresh = np.zeros(thresh.shape, dtype=np.uint8)
newthresh = cv2.drawContours(newthresh, cont, -1, 255, -1)

# Performing erosion->dilation to remove noise(specifically white portions detected of the poker coins).
kernel = np.ones((3, 3), dtype=np.uint8)
newthresh = cv2.erode(newthresh, kernel, iterations=6)
newthresh = cv2.dilate(newthresh, kernel, iterations=6)

# Again finding the final contours and drawing them on the image.
cont, hier = cv2.findContours(newthresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cv2.drawContours(imgC, cont, -1, (255, 0, 0), 2)

# Showing image
cv2.imshow("contours", imgC)
cv2.waitKey(0)

Results -结果 -

卡1输出 卡2输出

With this, we got the boundary of the cards in the image.这样,我们就得到了图像中卡片的边界。 To detect and separate each individual card, a more complex algorithm will be required or it can be done by using deep learning model.要检测和分离每张卡片,需要更复杂的算法,或者可以使用深度学习 model 来完成。

I'm detecting the white rectangles inside your shape.我正在检测您的形状内的白色矩形。 The final result is the detected image and the bounding box coordinates.最终结果是检测到的图像和边界框坐标。 The script isn't complete yet.剧本还没有完成。 I'll try to continue it in the next couple of days.我会在接下来的几天里继续尝试。

import os
import cv2
import numpy as np


def rectangle_detection(img):    
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    _, binarized = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    cn = cv2.dilate(binarized, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11)), iterations=3)
    cn = cv2.erode(cn, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15, 15)), iterations=3)
    cn = cv2.dilate(cn, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)), iterations=3)

    _, contours, _ = cv2.findContours(binarized, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    # contours = sorted(contours, key=lambda x: cv2.contourArea(x))

    # detect all rectangles
    rois = []
    for contour in contours:
        cont_area = cv2.contourArea(contour)
        approx = cv2.approxPolyDP(contour, 0.02*cv2.arcLength(contour, True), True)
        if 1000 < cont_area < 15000:
            x, y, w, h = cv2.boundingRect(contour)
            rect_area = w * h
            if cont_area / rect_area < 0.6: # check the 'rectangularity'
                continue     
            cv2.drawContours(img, [approx], 0, (0, 255, 0), 2)
            if len(approx) == 4:
                cv2.putText(img, "Rect", (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255))
            rois.append((x, y, w, h))
    return img, rois


def main():
    # load and prepare images
    INPUT = 'path'
    img = cv2.imread(INPUT)
    display, rects = rectangle_detection(img)
    cv2.imshow('img', display)
    cv2.waitKey()


if __name__ == "__main__":
    main()

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用python和opencv互相减去两个图像? - How do I subtract two images from each other using python and opencv? 我如何将这些数据彼此分开 - How do i separate these data from each other 如何在同一图中的循环中绘制由函数生成的多个相互重叠的图? - How do I plot multiple plots generated from a function in a loop in the same figure overlapping each other? 我如何在python中彼此分离2个输出 - How do I seperate 2 outputs from each other in python 如何在python中分别打印系数和指数? - How to print coefficient and exponent separate from each other in python? 如何通过Pygame 2.5使2张单独的图像互相追逐并互相跟随? - How do I make 2 separate images chase each other and follow each other via Pygame 2.5? 如何使用openCV和Python在每个矩形块中填充颜色? - How do i fill color in each rectangle block using openCV and Python? 我如何遍历以逗号分隔的字符串中的每个条目,并使用 Python 将其作为单独的输入包含在内 - How do i loop through each entry in a string delimited by a comma and include it as a separate input using Python 如何在python的表中分隔每个tr? - how do I separate each tr in a table in python? 如何从图像中识别最大的边界矩形并使用 Opencv 和 python 将它们分成单独的图像 - How to identify largest bounding rectangles from an image and separate them into separate images using Opencv and python
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM