您可以查看本教程来检测图像中的倾斜角度并进行处理。本教程完整地说明了如何解决您的问题:
http://felix.abecassis.me/2011/09/opencv-detect-skew-angle/
包括以下链接教程的要点:
用 OpenCV 实现
首先,让我们声明一个函数compute_skew,它将图像的路径作为输入,并将检测到的角度输出到标准输出。
首先我们加载图像并将其大小存储在一个变量中,非常简单。
void compute_skew(const char* filename)
{
// Load in grayscale.
cv::Mat src = cv::imread(filename, 0);
cv::Size size = src.size();
在图像处理中,物体是白色的,背景是黑色的,相反,我们需要反转图像的颜色:
cv::bitwise_not(src, src);
结果如下:
为了计算偏斜,我们必须在文本中找到直线。在一个文本行中,我们有几个字母并排,因此应该通过在图像中找到长的白色像素行来形成行。下面是一个例子:
当然,由于字符有高度,我们从文本中为每一行找到几行。通过微调稍后使用的参数或使用预处理,我们可以减少行数。
那么,我们如何在图像中找到线条?我们使用一个强大的数学工具,称为霍夫变换。我不会深入研究数学细节,但霍夫变换的主要思想是使用 2D 累加器来计算在图像中找到给定线的次数,整个图像被扫描并由投票系统确定了“最佳”行。
我们使用了一种更有效的标准霍夫变换 (SHT) 变体,称为概率霍夫变换 (PHT)。在 OpenCV 中,PHT 以 HoughLinesP 的名称实现。
除了霍夫变换的标准参数外,我们还有两个附加参数:
minLineLength – 最小行长度。比这更短的线段将被拒绝。这是一个很好的工具,可以修剪掉小的残留线。
maxLineGap – 同一条线上的点之间的最大允许间隙以连接它们。
这对于多列文本可能很有趣,例如我们可以选择不链接来自不同文本列的行。
现在回到 C++,在 OpenCV 中,PHT 存储线的端点,而 SHT 将线存储在极坐标中(相对于原点)。我们需要一个向量来存储所有的端点:
std::vector<cv::Vec4i> lines;
我们现在准备好进行霍夫变换了:
cv::HoughLinesP(src, lines, 1, CV_PI/180, 100, size.width / 2.f, 20);
我们对 ρ 使用 1 步长,对 θ 使用 π/180,阈值(最小投票数)为 100。
minLineLength 是宽度/2,如果文本被很好地隔离,这不是一个不合理的假设。
maxLineGap 是 20,这似乎是一个合理的间隙值。
在剩下的代码中,我们简单地使用 atan2 数学函数计算每条线与水平线之间的角度,然后计算所有线的平均角度。
出于调试目的,我们还在一个名为 disp_lines 的新图像中绘制所有线条,并在新窗口中显示此图像。
cv::Mat disp_lines(size, CV_8UC1, cv::Scalar(0, 0, 0));
double angle = 0.;
unsigned nb_lines = lines.size();
for (unsigned i = 0; i < nb_lines; ++i)
{
cv::line(disp_lines, cv::Point(lines[i][0], lines[i][1]),
cv::Point(lines[i][2], lines[i][3]), cv::Scalar(255, 0 ,0));
angle += atan2((double)lines[i][3] - lines[i][1],
(double)lines[i][2] - lines[i][0]);
}
angle /= nb_lines; // mean angle, in radians.
std::cout << "File " << filename << ": " << angle * 180 / CV_PI << std::endl;
cv::imshow(filename, disp_lines);
cv::waitKey(0);
cv::destroyWindow(filename);
}
我们只需要一个 main 函数就可以在多个图像上调用 compute_skew:
const char* files[] = { "m8.jpg", "m20.jpg", "p3.jpg", "p16.jpg", "p24.jpg"};
int main()
{
unsigned nb_files = sizeof(files) / sizeof(const char*);
for (unsigned i = 0; i < nb_files; ++i)
compute_skew(files[i]);
}