主要流程:

1.首先得到灰度图像
2.对灰度图像进行二值化
3.然后找一个最小矩形框住对象轮廓(opencv中有相应的函数)
4.这个最小矩形的函数会返回一个角度
5.我们利用这个角度得到一个旋转的矩形(仿射变换所需要的)
6.使用仿射变换得到矫正后的图像

1.得到灰度图像

//读取图像
src= cv.imread('imageTextR.png')
(h,w)=src.shape[:2]
//记录图像宽高,后面会用
//cv.imshow('src',src)  
//cvtColor函数用于转换色彩空间,将图像转换为GRAY灰度图像
gray=cv.cvtColor(src,cv.COLOR_BGR2GRAY)

python通过拉一条直线扶正倾斜照片 python图像倾斜校正_灰度图像


这是我们需要矫正的图像

2.对灰度图像进行二值化

ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV|cv.THRESH_OTSU)
#由于文本是黑底白字的,我们需要让背景是黑色的,所以我们在传入参数的时候需要使用cv.THRESH_BINARY_INV 加上_INV使二值图反转

python通过拉一条直线扶正倾斜照片 python图像倾斜校正_灰度图像_02


这是二值图

3.找一个最小矩形框住对象轮廓

coords=np.column_stack(np.where(binary>0))

np.where(binary>0):可以理解为找出二值图中所有的白色

np.column_stack(np.where(binary>0)):将所有白色的像素统计起来

python通过拉一条直线扶正倾斜照片 python图像倾斜校正_opencv_03


这里可以看到返回的coords的大小是(24527,2)即二值图中共有24527个白色像素点。

4.得到矩形角度

接下使用cv的minAreaRect函数求出最小外接矩形,传入的参数要求为点集数组或向量。返回的参数有三个:1.矩形的中心点 2.矩形的长和宽 3.矩形的旋转角度

angle =cv.minAreaRect(coords)[-1] 
//[-1]表示返回参数中的最后一个,即角度

角度是根据这个规则来的:

python通过拉一条直线扶正倾斜照片 python图像倾斜校正_opencv_04


这里我们默认倾斜角度不是特别大,所以如果我们的倾斜角度大于-45度我们就将其矫正为水平的,如果小于-45度我们将其矫正为垂直的:

if angle<-45:
    angle = -(90+angle)
else:
    angle=-angle
center = (w//2,h//2)
//求出矩形中点

5.我们利用这个角度得到一个旋转变换的矩形(仿射变换所需要的)

使用cv.getRotationMatrix2D()来得到选择最小外接旋转矩形,3个参数分别为旋转中心,旋转角度,旋转后图像的缩放比例

M= cv.getRotationMatrix2D(center,angle,1.0)

6.使用仿射变换得到矫正后的图像

使用cv.warpAffine来进行仿射变换,传入参数为:需要处理的图像,旋转变换矩阵,宽高,flags:插值方法,borderMode:边界填充

rotated = cv.warpAffine(src,M,(w,h),flags=cv.INTER_CUBIC,borderMode=cv.BORDER_REPLICATE)

python通过拉一条直线扶正倾斜照片 python图像倾斜校正_python通过拉一条直线扶正倾斜照片_05


得到的矫正后的图片

如果觉得有用 点个赞哦 谢谢啦
最后附上完整代码:

import numpy as np
import cv2 as cv


def binary(img):
    gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
    ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV|cv.THRESH_OTSU)
    return binary

def  Transformation(img,src):
    coords=np.column_stack(np.where(img>0))
    print(coords)
    print(coords.shape)
    angle =cv.minAreaRect(coords)[-1]    #最小外接矩形

    print(angle)
    if angle<-45:
        angle = -(90+angle)
    else:
        angle=-angle
    center = (w//2,h//2)
    M= cv.getRotationMatrix2D(center,angle,1.0) #传入中心和角度 得到旋转矩形
    rotated = cv.warpAffine(src,M,(w,h),flags=cv.INTER_CUBIC,borderMode=cv.BORDER_REPLICATE)
    cv.putText(rotated,'Angle:{:.2f} degrees'.format(angle),(10,30),cv.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)#绘制文字
    cv.imshow('Rotated',rotated)


src= cv.imread('imageTextR.png')
(h,w)=src.shape[:2]
gray=cv.cvtColor(src,cv.COLOR_BGR2GRAY)
binary=binary(src)
Transformation(binary,src)
cv.imshow('src',src)
cv.imshow('binary',binary)
cv.waitKey(0)