opencv利用霍夫变换检测直线进行图片校正

利用霍夫变换检测直线,校正拍摄倾斜的图片

#include<opencv2\opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
#define ERROR 1234

//度数转换
double DegreeTrans(double theta)
{
 double res = theta / CV_PI * 180;
 return res;
}

//逆时针旋转图像degree角度(原尺寸)
void rotateImage(Mat src, Mat& img_rotate, double degree)
{
 //旋转中心为图像中心
 Point2f center;
 center.x = float(src.cols / 2.0);
 center.y = float(src.rows / 2.0);
 int length = 0;
 length = sqrt(src.cols*src.cols + src.rows*src.rows);
 //计算二维旋转的仿射变换矩阵
 Mat M = getRotationMatrix2D(center, degree, 1);
 warpAffine(src, img_rotate, M, Size(length, length), 1, 0, Scalar(255, 255, 255));//仿射变换,背景色填充为白色
}

//通过霍夫变换计算角度
double CalcDegree(const Mat &srcImage, Mat &dst)
{
 Mat midImage, dstImage;

 Canny(srcImage, midImage, 50, 200, 3);
 cvtColor(midImage, dstImage, CV_GRAY2BGR);

 //通过霍夫变换检测直线
 vector<Vec2f> lines;
 HoughLines(midImage, lines, 1, CV_PI / 180, 300, 0, 0);//第5个参数就是阈值,阈值越大,检测精度越高
 //cout << lines.size() << endl;

 //由于图像不同,阈值不好设定,因为阈值设定过高导致无法检测直线,阈值过低直线太多,速度很慢
 //所以根据阈值由大到小设置了三个阈值,如果经过大量试验后,可以固定一个适合的阈值。

 if (!lines.size())
 {
  HoughLines(midImage, lines, 1, CV_PI / 180, 200, 0, 0);
 }
 //cout << lines.size() << endl;

 if (!lines.size())
 {
  HoughLines(midImage, lines, 1, CV_PI / 180, 150, 0, 0);
 }
 //cout << lines.size() << endl;
 if (!lines.size())
 {
  cout << "没有检测到直线!" << endl;
  return ERROR;
 }
 float sum = 0;
 //依次画出每条线段
 for (size_t i = 0; i < lines.size(); i++)
 {
  float rho = lines[i][0];
  float theta = lines[i][1];
  Point pt1, pt2;
  //cout << theta << endl;
  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));
  //只选角度最小的作为旋转角度
  sum += theta;
  line(dstImage, pt1, pt2, Scalar(55, 100, 195), 1, CV_AA); //Scalar函数用于调节线段颜色
  imshow("直线探测效果图", dstImage);
 }
 float average = sum / lines.size(); //对所有角度求平均,这样做旋转效果会更好
 cout << "average theta:" << average << endl;
 double angle = DegreeTrans(average) - 90;
 rotateImage(dstImage, dst, angle);
 //imshow("直线探测效果图2", dstImage);
 return angle;
}

void ImageRecify(const char* pInFileName, const char* pOutFileName)
{
 double degree;
 Mat src = imread(pInFileName);
 imshow("原始图", src);
 int srcWidth, srcHight;
 srcWidth = src.cols;
 srcHight = src.rows;
 cout << srcWidth << " " << srcHight << endl;
 Mat dst;
 src.copyTo(dst);
 //倾斜角度矫正
 degree = CalcDegree(src, dst);
 if (degree == ERROR)
 {
  cout << "矫正失败!" << endl;
  return;
 }
 rotateImage(src, dst, degree);
 cout << "angle:" << degree << endl;
 imshow("旋转调整后", dst);

 Mat resulyImage = dst(Rect(0, 0, srcWidth, srcHight)); //根据先验知识,估计好文本的长宽,再裁剪下来
 imshow("裁剪之后", resulyImage);
 imwrite("recified.jpg", resulyImage);
}

int main()
{
 ImageRecify("jiao.jpg", "FinalImage.jpg");
 waitKey();
 return 0;
}

效果图如下所示:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • OpenCV实现图像边缘检测

    最近自己在做一个有关图像处理的小项目,涉及到图像的边缘检测.直线检测.轮廓检测以及角点检测等,本文首先介绍图像的边缘检测,使用的是Canny边缘检测算法,具体代码以及检测效果如下: 1.代码部分: // Image_Canny.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <cv.h> #include "highgui.h" using namespace cv; int _tmain(int

  • OpenCV实现人脸检测

    前段日子,写了个人脸检测的小程序,可以检测标记图片.视频.摄像头中的人脸.效果还行吧,用的是opencv提供人脸库.至于具体的人脸检测原理,找资料去啃吧. 环境:VS2013+OPENCV2.4.10+Win8.1 一.基于对话框的MFC 首先,新建一个基于对话框的MFC应用程序,命名为myFaceDetect(取消"安全开发周期(SDL)检查"勾选,我自己习惯取消这个). 放置Button,设置Button的ID和Caption. 图片按钮--ID:IDC_FACEDETECT 视频

  • 使用OpenCV实现检测和追踪车辆

    本文实例为大家分享了OpenCV实现检测和追踪车辆的具体代码,供大家参考,具体内容如下 完整源码GitHub 使用高斯混合模型(BackgroundSubtractorMOG2)对背景建模,提取出前景 使用中值滤波去掉椒盐噪声,再闭运算和开运算填充空洞 使用cvBlob库追踪车辆,我稍微修改了cvBlob源码来通过编译 由于要对背景建模,这个方法要求背景是静止的 另外不同车辆白色区域不能连通,否则会认为是同一物体 void processVideo(char* videoFilename) {

  • OpenCV利用背景建模检测运动物体

    本文实例为大家分享了OpenCV利用背景建模检测运动物体的具体代码,供大家参考,具体内容如下 #include <opencv\highgui.h> #include <stdio.h> int main( int argc, char** argv ){ IplImage* pFrame = NULL; IplImage* pFrImg = NULL; IplImage* pBkImg = NULL; CvMat* pFrameMat = NULL; CvMat* pFrMat

  • 基于openCV实现人脸检测

    openCV的人脸识别主要通过Haar分类器实现,当然,这是在已有训练数据的基础上.openCV安装在 opencv/opencv/sources/data/haarcascades_cuda(或haarcascades)中存在预先训练好的物体检测器(xml格式),包括正脸.侧脸.眼睛.微笑.上半身.下半身.全身等. openCV的的Haar分类器是一个监督分类器,首先对图像进行直方图均衡化并归一化到同样大小,然后标记里面是否包含要监测的物体.它首先由Paul Viola和Michael Jon

  • 基于OpenCv的运动物体检测算法

    基于一个实现的基于OpenCv的运动物体检测算法,可以用于检测行人或者其他运动物体. #include <stdio.h> #include <cv.h> #include <cxcore.h> #include <highgui.h> int main( int argc, char** argv ) //声明IplImage指针 IplImage* pFrame = NULL; IplImage* pFrImg = NULL; IplImage* pBk

  • 10个步骤Opencv轻松检测出图片中条形码

    本文为大家分享了Opencv轻松检测出图片中条形码的步骤,供大家参考,具体内容如下 1. 原图像大小调整,提高运算效率 2. 转化为灰度图 3. 高斯平滑滤波 4.求得水平和垂直方向灰度图像的梯度差,使用Sobel算子 5.均值滤波,消除高频噪声 6.二值化 7.闭运算,填充条形码间隙 8. 腐蚀,去除孤立的点 9. 膨胀,填充条形码间空隙,根据核的大小,有可能需要2~3次膨胀操作 10.通过findContours找到条形码区域的矩形边界 实现: #include "core/core.hpp

  • opencv实现图片与视频中人脸检测功能

    本文实例为大家分享了opencv实现人脸检测功能的具体代码,供大家参考,具体内容如下 第一章:反思与总结 上一篇博客我相信自己将人脸检测中的AdaBoost算法解释的非常清晰了,以及如何训练人脸检测的强分类器:人脸检测中AdaBoost算法详解.事后,自我感觉对这个人脸检测还是不够具体,所以自己抽了一下午的时间用opencv实现图片与视频中的人脸检测,下面是我用vs2013加opencv4.9来实现的.做一下声明,我的代码是参考OpenCV实现人脸检测的一个博客写的,非常感谢这位博主,我学到了很

  • opencv检测直线方法之形态学方法

    在阅读文献中,偶然发现使用使用形态学方法也可以检测直线,故做实验并记录. 使用该方法,需要定义一个长度为L的结构元素element,其大小应足够大以保留图像中的字符笔划,然而又恰好能检测出图像中最短的表格线. 定义如下两个结构element用以检测图中水平.竖直的表格线: Mat element1 = getStructuringElement(MORPH_RECT, Size(70, 1));// size的width应大于图像中的横向笔划 Mat element3 = getStructur

  • C++利用opencv实现人脸检测

    小编所有的帖子都是基于unbuntu系统的,当然稍作修改同样试用于windows的,经过小编的绞尽脑汁,把刚刚发的那篇python 实现人脸和眼睛的检测的程序用C++ 实现了,当然,也参考了不少大神的博客,下面我们就一起来看看: Linux系统下安装opencv我就再啰嗦一次,防止有些人没有安装没调试出来喷小编的程序是个坑, sudo apt-get install libcv-dev sudo apt-get install libopencv-dev 看看你的usr/share/opencv

随机推荐