gpt4 book ai didi

python-3.x - 当纸张本身上有打印的角/线时,如何找到纸张的角?

转载 作者:行者123 更新时间:2023-12-02 16:09:28 25 4
gpt4 key购买 nike

我在Python中使用openCV查找一张纸的角以使其变形。

img = cv2.imread(images[i])

corners = cv2.goodFeaturesToTrack(cv2.cvtColor(img,cv2.COLOR_BGR2GRAY),4,.01,1000,useHarrisDetector=True,k=.04)
corners = np.float32(corners)
print(corners)
ratio = 1.6
cardH = math.sqrt((corners[2][0][0] - corners[1][0][0]) * (corners[2][0][0] - corners[1][0][0]) + (corners[2][0][1] - corners[1][0][1]) * (
corners[2][0][1] - corners[1][0][1]))
cardW = ratio * cardH;
pts2 = np.float32(
[[corners[0][0][0], corners[0][0][1]], [corners[0][0][0] + cardW, corners[0][0][1]], [corners[0][0][0] + cardW, corners[0][0][1] + cardH],
[corners[0][0][0], corners[0][0][1] + cardH]])

M = cv2.getPerspectiveTransform(corners, pts2)

offsetSize = 500
transformed = np.zeros((int(cardW + offsetSize), int(cardH + offsetSize)), dtype=np.uint8);
dst = cv2.warpPerspective(img, M, transformed.shape)

之前:
https://imgur.com/a/H7HjFro

后:
https://imgur.com/a/OA6Iscq

从这些图像可以看到,它们检测的是纸张本身内部的边缘,而不是纸张的角落。我应该考虑完全使用其他算法吗?我很迷茫。

我尝试将最小欧几里德距离增加到1000,但这确实没有任何作用。

请注意,这不是真实的信息,这是在Kaggle上发现的虚假数据集。

kaggle数据集可以找到 https://www.kaggle.com/mcvishnu1/fake-w2-us-tax-form-dataset

最佳答案

这是在Python / OpenCV中执行此操作的一种方法。

请注意,找到的角是从最高角开始逆时针列出的。

  • 读取输入的
  • 转换为灰色
  • 高斯模糊
  • Otsu阈值
  • 形态学打开/关闭以清理阈值
  • 获取最大轮廓
  • 从轮廓
  • 近似多边形
  • 获取角落
  • 在输入
  • 上绘制多边形
  • 计算边长
  • 计算输出对应的角点
  • 从相应的角点获取透视变换矩阵
  • 根据矩阵
  • 扭曲输入图像
  • 保存结果

  • 输入:

    enter image description here
    import cv2
    import numpy as np

    # read image
    img = cv2.imread("efile.jpg")

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

    # blur image
    blur = cv2.GaussianBlur(gray, (3,3), 0)

    # do otsu threshold on gray image
    thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]

    # apply morphology
    kernel = np.ones((7,7), np.uint8)
    morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
    morph = cv2.morphologyEx(morph, cv2.MORPH_OPEN, kernel)

    # get largest contour
    contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    area_thresh = 0
    for c in contours:
    area = cv2.contourArea(c)
    if area > area_thresh:
    area_thresh = area
    big_contour = c

    # draw white filled largest contour on black just as a check to see it got the correct region
    page = np.zeros_like(img)
    cv2.drawContours(page, [big_contour], 0, (255,255,255), -1)

    # get perimeter and approximate a polygon
    peri = cv2.arcLength(big_contour, True)
    corners = cv2.approxPolyDP(big_contour, 0.04 * peri, True)

    # draw polygon on input image from detected corners
    polygon = img.copy()
    cv2.polylines(polygon, [corners], True, (0,0,255), 1, cv2.LINE_AA)
    # Alternate: cv2.drawContours(page,[corners],0,(0,0,255),1)

    # print the number of found corners and the corner coordinates
    # They seem to be listed counter-clockwise from the top most corner
    print(len(corners))
    print(corners)

    # for simplicity get average of top/bottom side widths and average of left/right side heights
    # note: probably better to get average of horizontal lengths and of vertical lengths
    width = 0.5*( (corners[0][0][0] - corners[1][0][0]) + (corners[3][0][0] - corners[2][0][0]) )
    height = 0.5*( (corners[2][0][1] - corners[1][0][1]) + (corners[3][0][1] - corners[0][0][1]) )
    width = np.int0(width)
    height = np.int0(height)

    # reformat input corners to x,y list
    icorners = []
    for corner in corners:
    pt = [ corner[0][0],corner[0][1] ]
    icorners.append(pt)
    icorners = np.float32(icorners)

    # get corresponding output corners from width and height
    ocorners = [ [width,0], [0,0], [0,height], [width,height] ]
    ocorners = np.float32(ocorners)

    # get perspective tranformation matrix
    M = cv2.getPerspectiveTransform(icorners, ocorners)

    # do perspective
    warped = cv2.warpPerspective(img, M, (width, height))

    # write results
    cv2.imwrite("efile_thresh.jpg", thresh)
    cv2.imwrite("efile_morph.jpg", morph)
    cv2.imwrite("efile_polygon.jpg", polygon)
    cv2.imwrite("efile_warped.jpg", warped)

    # display it
    cv2.imshow("efile_thresh", thresh)
    cv2.imshow("efile_morph", morph)
    cv2.imshow("efile_page", page)
    cv2.imshow("efile_polygon", polygon)
    cv2.imshow("efile_warped", warped)
    cv2.waitKey(0)

    阈值图片:

    enter image description here

    形态清除图像:

    enter image description here

    在输入上绘制的多边形:

    enter image description here

    提取的角(从右上角逆时针方向)
    4

    [[[693 67]]
    [[ 23 85]]
    [[ 62 924]]
    [[698 918]]]

    扭曲的结果:

    enter image description here

    关于python-3.x - 当纸张本身上有打印的角/线时,如何找到纸张的角?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60941012/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com