Pet*_*r S 7 python ocr opencv image-processing skew
目前,我正在从事一个 OCR 项目,我需要从标签中读取文本(请参见下面的示例图像)。我遇到了图像倾斜问题,我需要帮助修复图像倾斜,以便文本水平而不是倾斜。目前,我正在尝试从给定范围内对不同角度进行评分(下面包含代码)的过程,但这种方法不一致,有时过度校正图像歪斜或平坦无法识别歪斜并纠正它。请注意,在倾斜校正之前,我将所有图像旋转 270 度以使文本直立,然后我通过下面的代码传递图像。传递给函数的图像已经是二进制图像。
代码:
def findScore(img, angle):
"""
Generates a score for the binary image recieved dependent on the determined angle.\n
Vars:\n
- array <- numpy array of the label\n
- angle <- predicted angle at which the image is rotated by\n
Returns:\n
- histogram of the image
- score of potential angle
"""
data = inter.rotate(img, angle, reshape = False, order = 0)
hist = np.sum(data, axis = 1)
score = np.sum((hist[1:] - hist[:-1]) ** 2)
return hist, score
def skewCorrect(img):
"""
Takes in a nparray and determines the skew angle of the text, then corrects the skew and returns the corrected image.\n
Vars:\n
- img <- numpy array of the label\n
Returns:\n
- Corrected image as a numpy array\n
"""
#Crops down the skewImg to determine the skew angle
img = cv2.resize(img, (0, 0), fx = 0.75, fy = 0.75)
delta = 1
limit = 45
angles = np.arange(-limit, limit+delta, delta)
scores = []
for angle in angles:
hist, score = findScore(img, angle)
scores.append(score)
bestScore = max(scores)
bestAngle = angles[scores.index(bestScore)]
rotated = inter.rotate(img, bestAngle, reshape = False, order = 0)
print("[INFO] angle: {:.3f}".format(bestAngle))
#cv2.imshow("Original", img)
#cv2.imshow("Rotated", rotated)
#cv2.waitKey(0)
#Return img
return rotated
Run Code Online (Sandbox Code Playgroud)
校正前和校正后的标签示例图像
如果有人能帮我解决这个问题,那将会有很大帮助。
nat*_*ncy 15
这是用于确定偏斜的投影轮廓方法的实现。获得二值图像后,想法是以各种角度旋转图像并在每次迭代中生成像素的直方图。为了确定倾斜角度,我们比较峰值之间的最大差异并使用此倾斜角度,旋转图像以校正倾斜
左(原始),右(更正)

import cv2
import numpy as np
from scipy.ndimage import interpolation as inter
def correct_skew(image, delta=1, limit=5):
def determine_score(arr, angle):
data = inter.rotate(arr, angle, reshape=False, order=0)
histogram = np.sum(data, axis=1)
score = np.sum((histogram[1:] - histogram[:-1]) ** 2)
return histogram, score
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
scores = []
angles = np.arange(-limit, limit + delta, delta)
for angle in angles:
histogram, score = determine_score(thresh, angle)
scores.append(score)
best_angle = angles[scores.index(max(scores))]
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, best_angle, 1.0)
rotated = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, \
borderMode=cv2.BORDER_REPLICATE)
return best_angle, rotated
if __name__ == '__main__':
image = cv2.imread('1.png')
angle, rotated = correct_skew(image)
print(angle)
cv2.imshow('rotated', rotated)
cv2.imwrite('rotated.png', rotated)
cv2.waitKey()
Run Code Online (Sandbox Code Playgroud)
小智 5
要添加@nathancy答案,对于 Windows 用户,如果您遇到额外的偏差,只需添加 dtype=float. 每当您创建 numpy 数组时。Windows 存在整数溢出问题,因为与其他系统不同,它分配 int(32) 位作为数据类型。
参见下面的代码;添加到方法dtype=float中np.sum():
import cv2
import numpy as np
from scipy.ndimage import interpolation as inter
def correct_skew(image, delta=1, limit=5):
def determine_score(arr, angle):
data = inter.rotate(arr, angle, reshape=False, order=0)
histogram = np.sum(data, axis=1, dtype=float)
score = np.sum((histogram[1:] - histogram[:-1]) ** 2, dtype=float)
return histogram, score
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
scores = []
angles = np.arange(-limit, limit + delta, delta)
for angle in angles:
histogram, score = determine_score(thresh, angle)
scores.append(score)
best_angle = angles[scores.index(max(scores))]
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, best_angle, 1.0)
rotated = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, \
borderMode=cv2.BORDER_REPLICATE)
return best_angle, rotated
if __name__ == '__main__':
image = cv2.imread('1.png')
angle, rotated = correct_skew(image)
print(angle)
cv2.imshow('rotated', rotated)
cv2.imwrite('rotated.png', rotated)
cv2.waitKey()
Run Code Online (Sandbox Code Playgroud)