【问题标题】:correctly rotate or flip images [invoices,forms] to its correct orientation in python在python中正确旋转或翻转图像[发票,表格]到正确的方向
【发布时间】:2020-06-03 14:39:02
【问题描述】:

我正在尝试将包含发票和表格的图像旋转到正确的方向。我试图找到角度,然后旋转图像。只有少数图像被正确旋转。下面是我尝试以正确方向旋转的代码和图像,第一个图像旋转正确,其他图像旋转不正确


import numpy as np
import cv2
import math
from scipy import ndimage

img_before = cv2.imread('rotate_me.png')

cv2.imshow("Before", img_before)    
key = cv2.waitKey(0)

img_gray = cv2.cvtColor(img_before, cv2.COLOR_BGR2GRAY)
img_edges = cv2.Canny(img_gray, 100, 100, apertureSize=3)
lines = cv2.HoughLinesP(img_edges, 1, math.pi / 180.0, 100, minLineLength=100, maxLineGap=5)

angles = []

for x1, y1, x2, y2 in lines[0]:
    cv2.line(img_before, (x1, y1), (x2, y2), (255, 0, 0), 3)
    angle = math.degrees(math.atan2(y2 - y1, x2 - x1))
    angles.append(angle)

median_angle = np.median(angles)
img_rotated = ndimage.rotate(img_before, median_angle)

print "Angle is {}".format(median_angle)
cv2.imwrite('rotated.jpg', img_rotated) 

第一张图片-[左侧倒置]---旋转后正确旋转 第二张图片--右侧倒置--旋转错误 两个图像都有 -90 度角。最终输出必须像 image3

https://i.stack.imgur.com/XpFVy.png

https://i.stack.imgur.com/bGI3k.png

https://i.stack.imgur.com/jHNgD.png

【问题讨论】:

  • 目前您使用的直线角度仅给出 -90,因为角度为 -90 的直线和角度为 90 的直线是相同的。这种方法不适用于 180 度旋转。请描述您的数据集是否有任何共同的徽标或其他文本。请提供有关您的数据集的其他信息。
  • so @RavitejaNarra 大多数数据是发票,其中也可以包含徽标。有些图像没有徽标,有些图像采用表格形式。我拥有不同类型的数据。但所需的方向输出与我附加的图像 3 相同

标签: python opencv image-processing python-imaging-library opencv-contour


【解决方案1】:

我建议不要寻找线条,而是寻找彩色区域。

如果该区域在图像的右侧,则需要旋转图像。

找到有色区域的方法如下:

  • 计算每两个颜色通道之间的绝对差值,并将结果相加。
    结果在有颜色(不是黑色/白色)的地方具有很高的值。
  • 应用阈值 - 低于阈值的值将为零(视为黑色/白色),高于阈值的值为 255(彩色像素)。
  • 使用connectedComponentsWithStats 查找阈值图像中的最大簇。
  • 如果最大的白色簇的中心在右侧,则旋转图像。

这是一个代码示例:

import numpy as np
import cv2

im = cv2.imread("rotate_me1.png", cv2.IMREAD_UNCHANGED);

# Compute difference between each two color channels for finding colored pixels.
cdiff = cv2.absdiff(im[:,:,0], im[:,:,1])//3 + cv2.absdiff(im[:,:,0], im[:,:,2])//3 + cv2.absdiff(im[:,:,1], im[:,:,2])//3;
ret, cmask = cv2.threshold(cdiff, 10, 255, cv2.THRESH_BINARY)

# Find clusters.
# https://answers.opencv.org/question/194566/removing-noise-using-connected-components/
nlabel,labels,stats,centroids = cv2.connectedComponentsWithStats(cmask, connectivity=8)

# Find second largest cluster (the largest is the background?):
stats[np.argmax(stats[:, cv2.CC_STAT_AREA])] = 0
idx_max_size = np.argmax(stats[:, cv2.CC_STAT_AREA])
center = centroids[idx_max_size]

# True if the center of the centroid is at the right side of the image
is_center_at_right_side = center[0] > im.shape[1]//2

if is_center_at_right_side:
    rotated_im = im[::-1, ::-1, :].copy()  # Reverse left/right and up/down
    cv2.imshow('rotated_im', rotated_im)

# Draw green circle at the center (for testing)
cv2.circle(im, (int(center[0]), int(center[1])), 10, (0, 255, 0), thickness=10)

cv2.imshow('cmask', cmask)
cv2.imshow('im', im)
cv2.waitKey(0)
cv2.destroyAllWindows()

cmask 的示例:

用绿色圆圈标记最大簇的中心:

旋转图片:


更新:

旋转90度:

# https://stackoverflow.com/questions/2259678/easiest-way-to-rotate-by-90-degrees-an-image-using-opencv
if is_center_at_right_side:
    rotated_im = cv2.rotate(im, cv2.ROTATE_90_COUNTERCLOCKWISE)
else:
    rotated_im = cv2.rotate(im, cv2.ROTATE_90_CLOCKWISE)

结果:

【讨论】:

  • 我正在寻找的输出就像我附加的 image3(一种横向上视图)而不是左右。在每种情况下都需要一个输出,如图 3 所示
  • 我在帖子中添加了更新。见Easiest way to rotate by 90 degrees
  • 嗨@rotem 感谢您的解决方案。对于这些情况,它工作得很好,但是如果图像已经是正确的形式,假设输入图像是 image3 那么为什么它被旋转它应该被修复..请帮助在这个
  • 在这种情况下,输入图像的尺寸差异很大(方向正确时宽度远大于高度)。我认为检查红蓝色圆圈是在顶部还是底部并不是一个真正的挑战,但在您发布的示例中没有任何意义。
  • 你真的希望我回答我看不到的图像吗?答案不针对一般情况,仅针对您发布的案例。不要期望得到一个完整的工作解决方案作为 Stack Overflow 站点的答案。将答案视为一种指导,并针对具体问题提供帮助。
猜你喜欢
  • 1970-01-01
  • 2019-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多