如何解决变换透视图函数错误地返回错误方向的图像

问题描述 投票:0回答:1

[请帮助我理解为什么会这样,如果可能的话,可以提供比我的补丁程序更好,更可靠的解决方案。

该功能基于this。问题是,在某些情况下图像轮廓会以错误的方向错误地弯曲:在固定旋转代码之前,图像轮廓已经朝上。因此,当它返回时,其方向不正确,其顶侧向左。轮廓为矩形(正确方向约为2991 x 2025),并正确地标识为宽度方向。

该功能主要是在这里尽可能地使裁剪后的矩形轮廓的方向更直;没有极端的情况,无论哪种方式都需要旋转> 45度,因为在此之前还有另一个功能可以解决这个问题。图像始终是矩形,而不是正方形,并且在代码中考虑了图像是横向(宽度>高度)还是纵向(高度>宽度)。您可以在上面的链接中查看其用例。

这里是代码:

def transform_perspective(img, corners):
    def reorder_corner_points(corners):
        tr, tl, bl, br = [(corner[0][0], corner[0][1]) for corner in corners][0:4]
        return tl, tr, br, bl

    # order the points in clockwise order
    ordered_corners = reorder_corner_points(corners)
    tl, tr, br, bl = ordered_corners

    # determine width of new image which is the max distance between
    # (bottom right and bottom left) or (top right and top left) x-coordinates
    width_A = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
    width_B = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
    width = max(int(width_A), int(width_B))

    # determine height of new image which is the max distance between
    # (top right and bottom right) or (top left and bottom left) y-coordinates
    height_A = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
    height_B = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    height = max(int(height_A), int(height_B))

    # construct new points to obtain top-down view of image in
    # tr, tl, bl, br order
    dimensions = np.array([[0, 0], [width - 1, 0], [width - 1, height - 1],
                           [0, height - 1]], dtype="float32")

    # convert to numpy format
    ordered_corners = np.array(ordered_corners, dtype="float32")

    # find perspective transform matrix
    matrix = cv2.getPerspectiveTransform(ordered_corners, dimensions)

    # get the transformed image,
    # should be its right side up is facing to the right,
    # height = img.shape[0] > width = img.shape[1]
    warped = cv2.warpPerspective(img, matrix, (width, height))

    # "rotate" -90 degrees to correct orientation
    warped = cv2.transpose(warped)
    warped = cv2.flip(warped, 0)

    return warped

我的补丁是在固定旋转之前简单地添加此if声明:

        # rotate the transformed image
        # rotate counter-clockwise once if landscape and length is greater than height
        # so that the fields to be extracted and read are right side up
        # skip rotating if it's already right side up for some reason.
        if (warped.shape[0] > warped.shape[1]) and config.is_landscape:
            warped = cv2.transpose(warped)
            warped = cv2.flip(warped, 0)

由于图像为风景,因此config.is_landscape设置为True。并考虑其他情况:

        if (warped.shape[0] < warped.shape[1]) and not config.is_landscape:
            warped = cv2.transpose(warped)
            warped = cv2.flip(warped, 0)

用于复制预处理等的完整代码。从上方粘贴到该函数之后。

# read and preprocess image
image = cv2.imread('asdasd.png', 1)
original = image.copy()
blur = cv2.bilateralFilter(image,9,75,75)
gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray,0,255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# get all contours
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

# get the largest contour
cnt = max(cnts, key=cv2.contourArea)

# warp
peri = cv2.arcLength(cnt, True)
transformed = transform_perspective(original, cv2.approxPolyDP(cnt, 0.05 * peri, True))

# show results
cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.imshow('transformed', transformed)
# cv2.imshow('rotated', rotated)
cv2.waitKey(0)

破坏了我的代码的图像:the image that broke my code

老实说,我不知道该图像和轮廓线有什么特殊之处或不同之处在于它破坏了代码。请参阅上一篇文章中的图像进行比较。我大多数其他图像的行为也与后者相似。

python image opencv image-processing contour
1个回答
0
投票

您调用了函数reorder_corner_points(corners):,但实际上并未实现任何排序/排序例程。

您必须从左上方正确排序点。

如果您正确执行,则在代码末尾不需要此:

# "rotate" -90 degrees to correct orientation
# warped = cv2.transpose(warped)
# warped = cv2.flip(warped, 0)

尝试一下:

    def reorder_corner_points(corners):
    Corners_ = []
    tr, tl, bl, br = [(corner[0][0], corner[0][1]) for corner in corners][0:4]
    for corner in corners:
        Corners_.append([(corner[0][0], corner[0][1])])

    Corners_ = np.reshape(Corners_, (-1, 2))
    # order the points in clockwise order
    ordered_corners = order_points(Corners_)
    return ordered_corners

订购功能:

def order_points(pts):
# Order along X axis
Xorder = pts[np.argsort(pts[:, 0]), :]

left = Xorder[:2, :]
right = Xorder[2:, :]

# Order along Y axis
left = left[np.argsort(left[:, 1]), :]
(tl, bl) = left

# use distance to get bottom right
D = dist.cdist(tl[np.newaxis], right, "euclidean")[0]
(br, tr) = right[np.argsort(D)[::-1], :]

return np.array([tl, tr, br, bl])
© www.soinside.com 2019 - 2024. All rights reserved.