使用 opencv 的 minAreaRect() 去偏斜 MNIST 数据集图像
Deskewing MNIST dataset images using minAreaRect() of opencv
我使用 opencv 的 minAreaRect 来校正 mnist digits.It 对大多数数字都很好,但在某些情况下,minAreaRect 未被正确检测到,这会导致数字进一步倾斜。
使用此代码的图像:
输入图像:
minAreaRect 图片:
校正图像:
但是,为此效果不佳:
输入图像:
minAreaRect 图片:
校正图像:
我想在这里提到我确实使用了:#coords = np.column_stack(np.where(thresh>0)) 但是,这根本不起作用。
请建议使用 opencv 的 minAreaRect(Preferred) 函数的解决方案。
我已经用几张图片进行了测试,我明白问题出在 最小面积矩形 的形成,在第二个例子中很明显,最小面积矩形是不可见的(因为它通过数字本身)。
代码如下:
import numpy as np
import cv2
image=cv2.imread('MNIST/mnist_png/testing/9/73.png')#for 4##5032,6780 #8527,2436,1391
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)## for 9 problem with 4665,8998,73,7
gray=cv2.bitwise_not(gray)
Gblur=cv2.blur(gray,(5,5))
thresh=cv2.threshold(Gblur,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
#cv2.imshow("gray_thresh_blur",thresh)
#Finding Contours will be used to draw the min area rectangle
_,contours,_=cv2.findContours(thresh.copy(),cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)
cnt1 = contours[0]
cnt=cv2.convexHull(contours[0])
angle = cv2.minAreaRect(cnt)[-1]
print("Actual angle is:"+str(angle))
rect = cv2.minAreaRect(cnt)
p=np.array(rect[1])
#print(p[0])
if p[0] < p[1]:
print("Angle along the longer side:"+str(rect[-1] + 180))
act_angle=rect[-1]+180
else:
print("Angle along the longer side:"+str(rect[-1] + 90))
act_angle=rect[-1]+90
#act_angle gives the angle with bounding box
if act_angle < 90:
angle = (90 + angle)
print("angleless than -45")
# otherwise, just take the inverse of the angle to make
# it positive
else:
angle=act_angle-180
print("grter than 90")
# rotate the image to deskew it
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated = cv2.warpAffine(image,M,(w,h),flags=cv2.INTER_CUBIC,borderMode=cv2.BORDER_REPLICATE)
box = cv2.boxPoints(rect)
print(box)
box = np.int0(box)
print(box)
p=cv2.drawContours(thresh,[box],0,(0,0,255),1)
print("contours"+str(p))
cv2.imwrite("post/MinAreaRect9.png",p)
cv2.imwrite("post/Input_9.png", image)
cv2.imwrite('post/Deskewed_9.png', rotated)
注意几点:
- OpenCV 的大部分功能都适用于白色前景和黑色背景。所以注释掉这一行:
gray=cv2.bitwise_not(gray)
- 确保您正在计算字母的 EXTERNEL 轮廓。这意味着您需要忽略所有子轮廓。为此使用
cv2.RETR_EXTERNAL
.
contours=cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[1]
- 最后确保您指定了正确的角度以找到旋转矩阵。
有了这些变化:
我使用 opencv 的 minAreaRect 来校正 mnist digits.It 对大多数数字都很好,但在某些情况下,minAreaRect 未被正确检测到,这会导致数字进一步倾斜。
使用此代码的图像:
输入图像:
minAreaRect 图片:
校正图像:
但是,为此效果不佳:
输入图像:
我想在这里提到我确实使用了:#coords = np.column_stack(np.where(thresh>0)) 但是,这根本不起作用。 请建议使用 opencv 的 minAreaRect(Preferred) 函数的解决方案。 我已经用几张图片进行了测试,我明白问题出在 最小面积矩形 的形成,在第二个例子中很明显,最小面积矩形是不可见的(因为它通过数字本身)。
代码如下:
import numpy as np
import cv2
image=cv2.imread('MNIST/mnist_png/testing/9/73.png')#for 4##5032,6780 #8527,2436,1391
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)## for 9 problem with 4665,8998,73,7
gray=cv2.bitwise_not(gray)
Gblur=cv2.blur(gray,(5,5))
thresh=cv2.threshold(Gblur,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
#cv2.imshow("gray_thresh_blur",thresh)
#Finding Contours will be used to draw the min area rectangle
_,contours,_=cv2.findContours(thresh.copy(),cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)
cnt1 = contours[0]
cnt=cv2.convexHull(contours[0])
angle = cv2.minAreaRect(cnt)[-1]
print("Actual angle is:"+str(angle))
rect = cv2.minAreaRect(cnt)
p=np.array(rect[1])
#print(p[0])
if p[0] < p[1]:
print("Angle along the longer side:"+str(rect[-1] + 180))
act_angle=rect[-1]+180
else:
print("Angle along the longer side:"+str(rect[-1] + 90))
act_angle=rect[-1]+90
#act_angle gives the angle with bounding box
if act_angle < 90:
angle = (90 + angle)
print("angleless than -45")
# otherwise, just take the inverse of the angle to make
# it positive
else:
angle=act_angle-180
print("grter than 90")
# rotate the image to deskew it
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated = cv2.warpAffine(image,M,(w,h),flags=cv2.INTER_CUBIC,borderMode=cv2.BORDER_REPLICATE)
box = cv2.boxPoints(rect)
print(box)
box = np.int0(box)
print(box)
p=cv2.drawContours(thresh,[box],0,(0,0,255),1)
print("contours"+str(p))
cv2.imwrite("post/MinAreaRect9.png",p)
cv2.imwrite("post/Input_9.png", image)
cv2.imwrite('post/Deskewed_9.png', rotated)
注意几点:
- OpenCV 的大部分功能都适用于白色前景和黑色背景。所以注释掉这一行:
gray=cv2.bitwise_not(gray)
- 确保您正在计算字母的 EXTERNEL 轮廓。这意味着您需要忽略所有子轮廓。为此使用
cv2.RETR_EXTERNAL
.
contours=cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[1]
- 最后确保您指定了正确的角度以找到旋转矩阵。
有了这些变化: