【问题标题】:Detect and crop card in image with multiple objects using width and height or color of card使用卡片的宽度和高度或颜色检测和裁剪具有多个对象的图像中的卡片
【发布时间】:2021-03-12 20:44:39
【问题描述】:

我有一张卡片,一张图片中有多个对象,我想使用卡片的宽度和高度或颜色裁剪卡片。

我可以使用以下代码进行裁剪:

import cv2
img = cv2.imread('/Users/akram/Downloads/img.jpg', 1)
x = 0
y = 0
width = 500
height = 500
cropped_img = img[y:y+height, x:x+width]
cv2.imshow("cropped_images", cropped_img)
cv2.waitKey(0)

但是当我有其他图像宽度卡width = 500 and height = 500x = 200 y = 100

我需要使用x = 200 and y = 100 编辑我的代码。

问题是我一直不知道卡片的位置,所以我需要创建一个动态代码来裁剪图像中任意位置 x 或 y 的卡片。

我不知道如何才能达到这个目的,我是 OpenCV 和计算机视觉方面的新手,实际上我是这个领域的新手。

示例图片

谁能帮我解决这个问题,谢谢?

【问题讨论】:

  • 你能发布一两张示例图片吗?
  • @AndriyMakukha 我添加图像通常图像可以有两个对象卡和签名,谢谢帮助!!
  • 您可以将卡片检测为轮廓,然后获取其周围的边界框,然后裁剪边界框。希望此链接对您有所帮助:docs.opencv.org/4.3.0/da/d0c/…

标签: python opencv image-processing deep-learning computer-vision


【解决方案1】:

您可以将卡片检测为轮廓,然后获取其周围的边界框,然后裁剪边界框。

希望此链接对您有所帮助:https://docs.opencv.org/4.3.0/da/d0c/tutorial_bounding_rects_circles.html

【讨论】:

    【解决方案2】:

    正如 Elyas Karimi 指出的那样,您可以通过查找轮廓来检测卡片。一种方法是找到输入图像的最大边界框,然后根据该边界框进行裁剪。对于示例图像,您将通过这种方式获得身份证。

    这是一个示例实现:

    #!/usr/bin/env python
    
    import cv2
    import numpy as np
    
    # load image
    img = cv2.imread('Image.jpg')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # convert to grayscale
    # threshold to get just the signature (INVERTED)
    retval, thresh_gray = cv2.threshold(gray, thresh=245, maxval=255, \
                                       type=cv2.THRESH_BINARY_INV)
    cv2.imwrite('Image_gray.jpg', thresh_gray)  # debugging
    
    contours, hierarchy = cv2.findContours(thresh_gray,cv2.RETR_LIST, \
                                       cv2.CHAIN_APPROX_SIMPLE)
    
    # Find object with the biggest bounding box
    mx = (0,0,0,0)      # biggest bounding box so far
    mx_area = 0
    for cont in contours:
        x,y,w,h = cv2.boundingRect(cont)
        area = w*h
        if area > mx_area:
            mx = x,y,w,h
            mx_area = area
    x,y,w,h = mx
    
    # Crop and save
    roi=img[y:y+h,x:x+w]
    cv2.imwrite('Image_crop.jpg', roi)
    
    # Draw bounding box rectangle (debugging)
    cv2.rectangle(img,(x,y),(x+w,y+h),(200,0,0),2)
    cv2.imwrite('Image_cont.jpg', img)
    

    您还可以在检测到的卡片下方找到最大的边界框来获取签名(或为此使用层次结构)。

    输入图片:

    边界框:

    作物:

    【讨论】:

    • 如果我有两张相同宽度和高度的卡片,我怎样才能得到两张卡片,每张卡片的名称,例如 id_card.jpg 和 bank_card.jpg 和 signature.png ?如果你想我发布新问题没问题,谢谢你非常匹配!
    • @A.khalifa,您可以阅读我的解决方案here,了解如何找到所有顶级轮廓。 (注意hierarchy[i][3] == 1需要用最新版cv2改成hierarchy[i][3] == -1)。
    • 谢谢@AndriyMakukha
    • 嗨@AndriyMakukha 你能分享Java代码吗?您上面的解决方案看起来不错。
    • @FalduJaldeep,不,我没有 Java 代码。
    【解决方案3】:

    首先找到阈值图像的轮廓,然后使用矩形找到表示该区域的最大区域。裁剪区域并保存。

    import cv2
    
    img=cv2.imread("1.jpg")
    img=cv2.resize(img,(1080,800))  #resize
    imgGrey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    _, threshold = cv2.threshold(imgGrey, 245, 255, cv2.THRESH_BINARY_INV) #thresholding
    contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    if contours:
        contours = max(contours, key=lambda x: cv2.contourArea(x)) #max contours finding using area
        x, y, w, h = cv2.boundingRect(contours)
        cv2.rectangle(img,(x,y),(x+w,y+h),[0,0,255],1)
        crop_img=img[y+1:y+h,x+1:x+w]  #crop the area
        cv2.imwrite("Crop_Image.jpg",crop_img) # save crop img
    cv2.imshow("selected area",img)
    cv2.imshow("croped area",crop_img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    输出:

    【讨论】:

      猜你喜欢
      • 2020-07-04
      • 2020-01-23
      • 2016-09-14
      • 1970-01-01
      • 2020-10-12
      • 1970-01-01
      • 1970-01-01
      • 2018-07-16
      • 2019-11-12
      相关资源
      最近更新 更多