/*
*形态学操作应用-提取水平与垂直直线
有很多种方法都可以提取到水平和垂直的线,但是要找出一种最适合你项目运用的,贴近你项目实际需求包括软件和硬件的需求的计算的速度等等各方面能符合你要求的一个提取的方法还是很不容易的
*原理方法
图像形态学操作时候,可以通过自定义的结构元素实现结构元素对输入图像一些对象敏感,另外一些对象不敏感,这样就会让敏感的对象改变
而不敏感的对象输出,通过使用最基本的两个形态学操作-膨胀和腐蚀,使用不同的结构元素实现对输入图像的操作、得到想要的结果
想得到水平线就要把不是水平线的那些给去掉,它对我们是一个干扰,我们就可以通过定义一个水平或者垂直的一个线的,比如垂直线对水平线有干扰,我们通过定义一个垂直的结构覆盖这个垂直线对垂直线来说它被结构元素覆盖了它就被去除掉了就得到了水平线,
同样对垂直线来说定义一个水平的就可以把水平的部分给去掉,
如果一个图像里面有很多垂直和水平的直线就可以通过这个方法把它分离出来,通过开操作根据不同的结构元素,二值图像和灰度图像的膨胀操作
*提取步骤
1.输入图像彩色图像 imread
2.转换为灰度图像 cvtColor
3.转换为二值图像 adaptiveThreshold,通过自适应阈值进行转换
(补充adaptiveThreshold参数说明:
Mat src 输入的灰度图像
Mat dest 二值图像
double maxValue 二值图像最大值
int adaptiveMethod 自适应方法,只能其中之一:ADAPTIVE_THRESH_MEAN_C,自适应方法,只能其中之一:ADAPTIVE_THRESH_GAUSSIAN_C
int adaptiveType 阈值类型
int blockSize 块大小
double C 常量C可以是正数,0,负数)
4.定义结构元素
5.开操作(腐蚀+膨胀)提取水平于垂直线
*/
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat src;
src = imread("D:/A_Graduation/Learning/opencv/learningOpencv/4.png");
namedWindow("src", CV_WINDOW_AUTOSIZE);
imshow("src", src);
//转换为灰度图像
Mat gray_src;
cvtColor(src, gray_src, CV_BGR2GRAY);
imshow("gray_src", gray_src);
//灰度图像转换为二值图像 ~gray_src中的~是取反之后再做转换 自适应阈值的方法 阈值的取值叫二值化,用阈值把它二值化
Mat bin_img;
adaptiveThreshold(~gray_src, bin_img, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY,15, -2);
imshow("bin_img", bin_img);
//得到结构元素 形状 大小 锚点
Mat hline = getStructuringElement(MORPH_RECT, Size(src.cols / 16, 1), Point(-1, -1)); //水平结构元素
Mat vline = getStructuringElement(MORPH_RECT, Size(1, src.rows / 16), Point(-1, -1)); //垂直结构元素
Mat rect = getStructuringElement(MORPH_RECT, Size(4, 4), Point(-1, -1)); //矩形结构元素
//提取水平线,先腐蚀后膨胀,膨胀和腐蚀要使用相同的结构元素
Mat res, temp; //temp是中间图像,相当于临时参数
erode(bin_img, temp, hline);
dilate(temp, res, hline);
bitwise_not(res, res); //把背景变成了白色
imshow("hline_result", res); //水平线保留,竖直线敏感,当水平的结构体经过那些地方的时候先腐蚀的时候最小值是黑色,那些白色都被黑色所替换掉了,相当于把它们一行行的全部擦除掉了,但是当结构体进过水平线的时候完全覆盖全是白色,所以它就保留下来了
//提取垂直线
// erode(bin_img, temp, vline);
// dilate(temp, res, vline);
morphologyEx(bin_img, res, CV_MOP_OPEN, vline);//直接用开操作CV_MOP_OPEN
bitwise_not(res, res); //把背景变成了白色
blur(res, res, Size(3, 3), Point(-1, -1)); //效果会好一点
imshow("vline_result", res);
//应用:去掉OCR验证码的干扰线
erode(bin_img, temp, rect);
dilate(temp, res, rect);
bitwise_not(res, res); //把背景变成了白色
imshow("rect_result", res);
waitKey(0);
return 0;
}