本博客路面有效区域分割采用先将原始图使用加权平均法取灰度图然后进行中值滤波,二值化,Canny边缘检测,概率霍夫变换取直线,随后将霍夫变换取的直线由笛卡尔坐标转换为极坐标,设置阈值筛选有效直线然后画直线的两端延长线,进而求交点,包括用两点式求出直线与图边缘交点(本例图分辨率为626×141),之后取ROI区域掩码图与原图合并得到最终分割结果。程序最后提供开运算效果与可变的二值化操作(包含二进制阈值,反二进制阈值,截断阈值,反阈值化为0,阈值化为0四个模式)以及图片的腐蚀膨胀用于消去一部分阴影干扰(注:需要根据不同场景更改极坐标阈值以及与所取有效直线与图像边缘交点):
#include <iostream>
#include<cmath>
#include "cv.h"
#include "highgui.h"
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
#define RAD_TO_DEG (180/(4*atan(1)))//pi=4*atan(1)
Mat src, src1, dst1, dst2, dst3, dst4,dst5, dst6,dst7,dst8;
Vec4i temp1, temp2;
double Left_x, Left_y, Right_x, Right_y;
int g_nThresholdValue = 47;
int g_nThresholdType = 1;
int g_nTrackbarNumer = 0;//0表示腐蚀erode, 1表示膨胀dilate
int g_nStructElementSize = 1; //结构元素(内核矩阵)的尺寸
int g_element = 2;
typedef struct polar_y {
double magnitude;//与极点的距离
double angle;//角度
}POLAR_V;
typedef struct rect_v {
double x;
double y;
}RECT_V;
void cvtCOLOR(Mat src, Mat dst)//加权平均法求灰度值
{
float R, G, B;
for (int y = 0; y < src.rows; y++)
{
uchar* data = dst.ptr<uchar>(y);
for (int x = 0; x < src.cols; x++)
{
B = src.at<Vec3b>(y, x)[0];
G = src.at<Vec3b>(y, x)[1];
R = src.at<Vec3b>(y, x)[2];
data[x] = (int)(R * 0.299 + G * 0.587 + B * 0.114);//利用公式计算灰度值(加权平均法)
}
}
}
void OnDrawDotline(Point s, Point e,Mat workimg)//画延长线
{
Point pa,pb;
double k=(s.y-e.y)/(s.x-e.x+0.000001);//不加0.000001 会变成曲线,斜率可能为0,即e.x-s.x可能为0
double h = workimg.rows;//height
double w = workimg.cols;//width
pa.x=w;
pa.y=s.y+k*(w-s.x);
//向右画线
line(workimg, e, pa, CV_RGB(0, 255, 255), 2, LINE_AA);
pb.y=e.y-k*e.x;
pb.x=0;
//向左画线
line(workimg, pb, s, CV_RGB(0, 255, 255), 2, LINE_AA);
}
Point2f getCrossPoint(Vec4i LineA, Vec4i LineB)//取交点
{
double ka, kb;
ka = (double)(LineA[3] - LineA[1]