OpenCV--基于直线检测的文本图像倾斜校正

图像倾斜矫正的方式有很多种,今天简单介绍一种基于直线检查的倾斜校正。

这种方法暂时在如下图的文本文件上测试过,不一定能针对所有:

首先,因为这种图像基本是比较常见的白底黑字,所以首先对这幅图做一个灰度化,灰度化之后做一个二值化,得到二值图像:

二值化之后,将X轴方向的的像素点连起来,这里我采用的是形态学的膨胀,因为我做二值化的时候采用了取反的操作,这里可以考虑不取反,但是要用腐蚀来做,这里有个技巧,因为是要对X轴来做连接,所以可以在构造形态学核上将Y轴设置为1:

做了连接后可以使用canny边缘检测做一遍边缘检测,然后再做霍夫变化:

从上图可以看出来基本上画出来的直线方向跟文字的走向的一致的,然后根据霍夫变换得到的角度来求平均值,这个平均值就是图像要旋转的角度。

上代码:

#include <opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

void GetContoursPic(const char* pSrcFileName)
{
	Mat srcImg = imread(pSrcFileName);
	imshow("原始图", srcImg);
	Mat gray, binImg;
	//灰度化
	cvtColor(srcImg, gray, COLOR_RGB2GRAY);
	imshow("灰度图", gray);
	//二值化
	threshold(gray, binImg, 50, 255, CV_THRESH_BINARY_INV );
	imshow("二值化", binImg);

	Mat morphologyDst;
	cv::morphologyEx(binImg, morphologyDst, cv::MORPH_DILATE, 
	    cv::getStructuringElement(cv::MORPH_RECT, cv::Size(7, 1)));
	imshow("膨胀", morphologyDst);

	Mat cannyDst;
	Canny(morphologyDst, cannyDst, 150, 200);
	imshow("Canny", cannyDst);

	vector<Vec2f> lines;
	HoughLines(cannyDst, lines, 1, CV_PI / 180, 130, 0, 0);
	Mat houghDst;
	srcImg.copyTo(houghDst);
	double meanAngle = 0.0;
	int numCnt = 0;
	for (size_t i = 0; i < lines.size(); i++)
	{
		float rho = lines[i][0]; //就是圆的半径r
		float theta = lines[i][1]; //就是直线的角度
		Point pt1, pt2;
		double a = cos(theta), b = sin(theta);
		double x0 = a*rho, y0 = b*rho;
		pt1.x = cvRound(x0 + 1000 * (-b));
		pt1.y = cvRound(y0 + 1000 * (a));
		pt2.x = cvRound(x0 - 1000 * (-b));
		pt2.y = cvRound(y0 - 1000 * (a));

		line(houghDst, pt1, pt2, Scalar(55, 100, 195), 1);
		
		theta = theta * 180 / CV_PI - 90;
		//if (theta > -45 && theta < 45)
		{
			meanAngle += theta;
			numCnt++;
		}
	}
	meanAngle /= numCnt;
	imshow("霍夫变换", houghDst);
	cv::Point2f center(srcImg.cols / 2., srcImg.rows / 2.);
	//获取旋转矩阵(2x3矩阵)
	cv::Mat rot_mat = cv::getRotationMatrix2D(center, meanAngle, 1.0);
	cv::Size dst_sz(srcImg.cols, srcImg.rows);
	Mat warpDst;
	cv::warpAffine(srcImg, warpDst, rot_mat, dst_sz);
	imshow("旋转矫正", warpDst);

	cv::waitKey(0);
}

结果如下:

这个方法有几个重要的影响点:

1、二值化:二值化的阈值选得不好的话结果是不能将前景和背景分离,我试过用OTSU,出来的二值化不是很好,然后检测直线的时候就有一点不太准确,但是基本上也能检测出来:

2、如果是白底黑字,就用腐蚀,反之有膨胀来做;

3、边缘检测也很重要,可想而知,不做边缘检测再来做霍夫变换,那得有多少条直线,直接冗余不说,还非常容易干扰检测。

4、另外,对于一些高度大于宽度的图像,其实可以采用分段检测求平均,以保证每一段的高度小于宽度,因为我的检测主要以X轴为主。

路漫漫其修远兮

吾将上下而求索

 

### OpenCV 文本图像垂直处理 对于文本图像的垂直操作,如旋转、矫正等变换,在OpenCV中有多种方法来实现这些需求。下面将详细介绍几种常见的处理方式。 #### 图像旋转 为了完成图像的旋转,可以使用`cv2.getRotationMatrix2D()`函数获取旋转变换矩阵,再通过`cv2.warpAffine()`应用该变换到原图上。此过程允许指定任意角度的顺时针或逆时针方向上的旋转[^1]。 ```python import cv2 import numpy as np def rotate_image(image, angle): (h, w) = image.shape[:2] center = (w // 2, h // 2) M = cv2.getRotationMatrix2D(center, angle, scale=1.0) rotated = cv2.warpAffine(image, M, (w, h)) return rotated ``` #### 文本校正 当涉及到文档扫描件中的文字倾斜问题时,可以通过检测边缘并计算倾斜角来进行自动化的文本校正。具体来说,先利用边缘检测算法找到轮廓线,接着拟合直线得到倾斜角度,最后按照上述提到的方法执行反向旋转调整[^2]。 ```python def correct_skew(image): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray, 50, 150, apertureSize=3) lines = cv2.HoughLinesP(edges, rho=1, theta=np.pi / 180, threshold=100, minLineLength=100, maxLineGap=10) angles = [] if lines is not None: for line in lines: x1, y1, x2, y2 = line[0] angle = np.arctan2(y2 - y1, x2 - x1) * 180 / np.pi angles.append(angle) avg_angle = sum(angles)/len(angles) if len(angles)>0 else 0 corrected_img = rotate_image(image,-avg_angle) return corrected_img ``` #### 形态学操作 除了简单的几何转换外,有时还需要对二值化后的文本区域做进一步优化,比如去除噪声点或是填补断开的文字连接部分。这时就可以借助于形态学膨胀(`cv2.dilate`)和腐蚀(`cv2.erode`)两个基本运算达成目的。 ```python kernel = np.ones((3, 3), dtype="uint8") dilated = cv2.dilate(binary_image, kernel, iterations=1) eroded = cv2.erode(dilated, kernel, iterations=1) ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值