• 图片的倾斜检测


    1、原理:

    计算图片里主要少数线条的平均角度,大于某个值则认为倾斜

    2、效果图:

    倾斜的(设角度大于12度为倾斜)

     正常的

     

     3、流程

    a、先对图片进行大小缩放,加快处理速度

    Mat srcPic = imread(pInFileName);
    	int cols=configText.resizeCols;
    	int rows=srcPic.rows/(srcPic.cols*1.00/cols);//按宽高比例缩放
    	Mat src =Mat::zeros(rows,cols , CV_8UC3);
    	resize(srcPic,src,src.size());
    

    b、如果要检索的图片具有共同的特征(都是货架且货架颜色相同)可采用阈值化二分,让边缘检测更有方向性(慎用!

    threshold(srcImage, srcThrImage, 40, 255, THRESH_BINARY);
    	imshow("阈值化后的效果图", srcThrImage);
    

    c、通过Canny算子进行边缘检测

    高阈值求边缘低阈值平滑边缘,可以将高低阈值的比率设置为足够大如factor=5使得边缘更加的平滑

    Canny(srcThrImage, midImage, cannyThreshold,cannyThreshold*factor);//Canny边缘检测算法,指定高低阈值(梯度幅值)
    

    d、根据边缘用HoughLinesP霍夫线变换检测直线,最终需要控制检测到的直线条数

    方法说明:

    霍夫变换使用极坐标来表示直线(极径rho和极角theta),一条直线能够通过在平面 	heta - r 寻找交于一点的曲线数量来检测

    CV_EXPORTS_W void HoughLinesP( InputArray image, OutputArray lines,
    double rho, double theta, int threshold,
    double minLineLength=0, double maxLineGap=0 );

    rho:就是一个半径的分辨率
    theta:角度分辨率
    threshold:判断直线点数的阈值
    minLineLength:线段长度阈值
    minLineGap:线段上最近两点之间的阈值(不大于此阈值则会认为是同一条直线上的点)

    注意:

    1、参数 threshold、minLineLength的设置很重要,关系到是否能过检测到线段及数量,需要根据目标图片的大小特征实验得到

    2、minLineGap建议设置为2会使实际的轮廓更多的识别为线段,太大也会导致识别太多的错误线段。

    HoughLinesP(midImage, lines, 1, CV_PI / 180, configText.thresholdVal, configText.minLineLength, configText.maxLineGap);//HoughLinesP霍夫线变换
    	while (lines.size()>10)//为了保持检查到的直线条数需要对threshold进行递减或递增
    	{
    		cannyThreshold+=10;
    		Canny(srcThrImage, midImage, cannyThreshold,cannyThreshold*factor);
    		cvtColor(midImage, dstImage, CV_GRAY2BGR);
    		HoughLinesP(midImage, lines, 1, CV_PI / 180, configText.thresholdVal, configText.minLineLength, configText.maxLineGap);
    	}
    	if (!lines.size())
    	{
    		cannyThreshold-=10;
    		Canny(srcThrImage, midImage, cannyThreshold,cannyThreshold*factor);
    		cvtColor(midImage, dstImage, CV_GRAY2BGR);
    		HoughLinesP(midImage, lines, 1, CV_PI / 180, configText.thresholdVal, configText.minLineLength, configText.maxLineGap);
    	}
    

    e、对检测到的线条计算平均角度用来判断是否倾斜

    注意:

    1、检测到最大角度不会超过45度

    2、保证检测到的线条数足够多(如50,太多会有很多无效的线段导致最终结果无意义),让计算的平均角度与实际更加的符合

    double DetectionSlope::GetAvgAngle(const vector<Vec4i>& lines){//通过直线求平均角度
    	double totalAngle=0;
    	for (auto & line : lines)
    	{
    		//360度=2π弧度
    		auto radian=atan(abs((line[3]-line[1])*1.0/(line[2]-line[0])));
    		auto angle=abs(360*radian/(2*CV_PI));
    		if(angle>45)
    			angle=abs(90-angle);
    		totalAngle+=angle;
    	}
    	return totalAngle/lines.size();
    }
    

    4、补充

    a、对于没有扭曲只是角度倾斜的图片可通过旋转来修正

    //逆时针旋转图像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));//仿射变换,背景色填充为白色  
    }
    

    b、对于存在扭曲的图片进行修正需要找到 四个角的坐标点,一般认为是检测到的直线的四个角度(这个不太靠谱,找准实际的四个点比较难)

    通过检测到的四个坐标点,形成源与目标的变换矩阵,再对图片进行透视变换

    	Mat m1 = Mat(srcTriangle);
    	Mat m2 = Mat(dstTriangle);
    	Mat status;
    	Mat h = findHomography(m1, m2, status, 0, 3);//获取单映射H(理解为两帐图片的点映射)
    	warpPerspective(this->srcImage, this->dstImage, h, this->dstImage.size());//对图像进行透视变换,就是变形
    

    参考:

    Canny边缘检测

    http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.html#canny-detector 

    threshold阈值操作

    http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/threshold/threshold.html#basic-threshold

    霍夫线变换

    http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html#hough-lines

    图像旋转

    https://blog.csdn.net/guduruyu/article/details/70799804

    Homography单映射

    https://blog.csdn.net/liuphahaha/article/details/50719275

    perspectiveTransform透视变换

    https://blog.csdn.net/xiaowei_cqu/article/details/26478135

    对倾斜的图像进行修正——基于opencv 透视变换 

    https://blog.csdn.net/MrCharles/article/details/73739693

    极坐标

    https://zhuanlan.zhihu.com/p/26172668

    本博客所有内容均为原创,转载请注明出处!谢谢
  • 相关阅读:
    3.2 Program Encodings 程序编码
    Describe your home
    Building vs solution in command line
    找到适合自己的人生轨迹 Angkor:
    每个月总有那么几天不想学习,不想写代码 Angkor:
    Linux下的Memcache安装
    敏捷开发之 12条敏捷原则
    为什么要用NIO
    memcached server LRU 深入分析
    Linux 脚本编写基础
  • 原文地址:https://www.cnblogs.com/hepc/p/8792954.html
Copyright © 2020-2023  润新知