如何对文本图像进行校正并检索该图像的新边界框 Python OpenCV?
How to de-skew a text image and retrieve the new bounding box of that image Python OpenCV?
这是我得到的一张收据图片,我用 matplotlib 绘制了它,如果你看到图片,里面的文字不是直的。我该如何消除和修复它?
from skimage import io
import cv2
# x1, y1, x2, y2, x3, y3, x4, y4
bbox_coords = [[20, 68], [336, 68], [336, 100], [20, 100]]
image = io.imread('https://i.ibb.co/3WCsVBc/test.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
fig, ax = plt.subplots(figsize=(20, 20))
ax.imshow(gray, cmap='Greys_r')
# for plotting bounding box uncomment the two lines below
#rect = Polygon(bbox_coords, fill=False, linewidth=1, edgecolor='r')
#ax.add_patch(rect)
plt.show()
print(gray.shape)
(847, 486)
我想如果我们想先消除倾斜我们必须找到边缘,所以我尝试使用 canny 算法找到边缘然后得到如下的轮廓。
from skimage import filters, feature, measure
def edge_detector(image):
image = filters.gaussian(image, 2, mode='reflect')
edges = feature.canny(image)
contours = measure.find_contours(edges, 0.8)
return edges, contours
fig, ax = plt.subplots(figsize=(20, 20))
ax.imshow(gray, cmap='Greys_r');
gray_image, contours = edge_detector(gray)
for n, contour in enumerate(contours):
ax.plot(contour[:, 1], contour[:, 0], linewidth=2)
我从上面的代码中得到的边缘是每个文本的边缘,但这不是我所需要的。我需要得到收据的边缘吗?
我还需要一种方法来在对图像进行去偏斜处理(即拉直图像)后获取新的边界框坐标吗?
如果有人解决过类似的问题,请帮助我?谢谢
这里是投影剖面法的修改实现,用于校正倾斜图像,如 JBIG 的基于投影剖面的倾斜估计算法中所述
压缩图像。在获得二值图像后,想法是将图像旋转各种角度,并在每次迭代中生成像素直方图。为了确定偏斜角,我们比较峰值之间的最大差异并使用此偏斜角旋转图像以校正偏斜。要确定的峰值数量可以通过 delta
值进行调整,delta 越低,将检查的峰值越多,但权衡过程将花费更长的时间。
之前->
之后
Skew angle: -2
代码
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)
corrected = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, \
borderMode=cv2.BORDER_REPLICATE)
return best_angle, corrected
if __name__ == '__main__':
image = cv2.imread('1.jpg')
angle, corrected = correct_skew(image)
print('Skew angle:', angle)
cv2.imshow('corrected', corrected)
cv2.waitKey()
注意: 您可能需要根据图像调整 delta
或 limit
值。 delta
值控制迭代步长,它将迭代到 limit
控制最大角度。此方法通过迭代检查每个角度 + delta
非常简单,目前仅适用于校正 +/- 5 度范围内的倾斜。如果需要在更大的角度进行校正,请调整 limit
值。对于另一种处理偏斜的方法,.
这是我得到的一张收据图片,我用 matplotlib 绘制了它,如果你看到图片,里面的文字不是直的。我该如何消除和修复它?
from skimage import io
import cv2
# x1, y1, x2, y2, x3, y3, x4, y4
bbox_coords = [[20, 68], [336, 68], [336, 100], [20, 100]]
image = io.imread('https://i.ibb.co/3WCsVBc/test.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
fig, ax = plt.subplots(figsize=(20, 20))
ax.imshow(gray, cmap='Greys_r')
# for plotting bounding box uncomment the two lines below
#rect = Polygon(bbox_coords, fill=False, linewidth=1, edgecolor='r')
#ax.add_patch(rect)
plt.show()
print(gray.shape)
(847, 486)
我想如果我们想先消除倾斜我们必须找到边缘,所以我尝试使用 canny 算法找到边缘然后得到如下的轮廓。
from skimage import filters, feature, measure
def edge_detector(image):
image = filters.gaussian(image, 2, mode='reflect')
edges = feature.canny(image)
contours = measure.find_contours(edges, 0.8)
return edges, contours
fig, ax = plt.subplots(figsize=(20, 20))
ax.imshow(gray, cmap='Greys_r');
gray_image, contours = edge_detector(gray)
for n, contour in enumerate(contours):
ax.plot(contour[:, 1], contour[:, 0], linewidth=2)
我从上面的代码中得到的边缘是每个文本的边缘,但这不是我所需要的。我需要得到收据的边缘吗?
我还需要一种方法来在对图像进行去偏斜处理(即拉直图像)后获取新的边界框坐标吗?
如果有人解决过类似的问题,请帮助我?谢谢
这里是投影剖面法的修改实现,用于校正倾斜图像,如 JBIG 的基于投影剖面的倾斜估计算法中所述
压缩图像。在获得二值图像后,想法是将图像旋转各种角度,并在每次迭代中生成像素直方图。为了确定偏斜角,我们比较峰值之间的最大差异并使用此偏斜角旋转图像以校正偏斜。要确定的峰值数量可以通过 delta
值进行调整,delta 越低,将检查的峰值越多,但权衡过程将花费更长的时间。
之前->
之后
Skew angle: -2
代码
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)
corrected = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, \
borderMode=cv2.BORDER_REPLICATE)
return best_angle, corrected
if __name__ == '__main__':
image = cv2.imread('1.jpg')
angle, corrected = correct_skew(image)
print('Skew angle:', angle)
cv2.imshow('corrected', corrected)
cv2.waitKey()
注意: 您可能需要根据图像调整 delta
或 limit
值。 delta
值控制迭代步长,它将迭代到 limit
控制最大角度。此方法通过迭代检查每个角度 + delta
非常简单,目前仅适用于校正 +/- 5 度范围内的倾斜。如果需要在更大的角度进行校正,请调整 limit
值。对于另一种处理偏斜的方法,