小白导读
学习计算机视觉最重要的能力应该就是编程了,为了帮助小伙伴尽快入门计算机视觉,小白准备了【OpenCV入门】系列。新的一年文章的内容进行了很大的完善,主要是借鉴了更多大神的文章,希望让小伙伴更加容易理解。如果小伙伴觉得有帮助,请点击一下文末的“好看”鼓励一下小白。
关于形态学的基本操作,上一篇文章已经进行了讲解,遗忘的小伙伴可以回去查看一下→形态学基本操作
提取步骤
输入图像彩色图像 imread
转换为灰度图像 – cvtColor
转换为二值图像 – adaptiveThreshold
相关函数
adaptiveThreshold(Mat src,Mat dest,double maxValue,int adaptiveMethod,int thresholdType,int blockSize,double C)
src:输入的灰度图像
dest:二值图像
maxValue:二值图像最大值
adaptiveMethod:自适应方法( ADAPTIVE_THRESH_MEAN_C ,ADAPTIVE_THRESH_GAUSSIAN_C)
thresholdType:阈值类型
blockSize:块大小
C:常量C 可以是正数,0,负数
定义结构元素
一个像素宽的水平线——水平长度width/30
一个像素宽的垂直线——垂直长度width/30
开操作 (腐蚀+膨胀)提取 水平与垂直线
程序代码
#include
#include
using namespace cv;
int main(int argc,char** argv){
//1、加载源图像,并检查它是否加载成功,然后显示它:
Mat src = imread("E:/Experiment/OpenCV/Pictures/paint1.jpg");
if(src.empty()){
printf("Could not load Image ...");
return -1;
}
namedWindow("1.input",CV_WINDOW_AUTOSIZE);
imshow("1.input",src);
//2、如果图像不是灰度图像转换为灰度图像:
Mat gray_src;
if (src.channels() == 3)
cvtColor(src,gray_src,CV_BGR2GRAY);
else
gray_src = src;
imshow("2.Gray Image",gray_src);
//3、然后将灰度图像转换为二值化。注意~符号表明我们使用逆操作后版本(即bitwise_not):
Mat binary_src;
/*
adaptiveThreshold( // 局部自适应阈值
Mat src, // 输入的灰度图像
Mat dest, // 二值图像
double maxValue, // 二值图像最大值
int adaptiveMethod // 自适应方法,只能其中之一 –
// ADAPTIVE_THRESH_MEAN_C , ADAPTIVE_THRESH_GAUSSIAN_C
int thresholdType,// 阈值类型 THRESH_BINARY THRESH_BINARY_INV 阈值 T = sum(blockSize X blockSize的像素平均值) - 常量C
int blockSize, // 块大小,只能为奇数,取图像宽或高的 1/4 到 1/6 之间? 要确保足够大?
double C // 常量C 可以是正数,0,负数 ,让结果变得更亮一点 更大一点?
)
*/
adaptiveThreshold(~gray_src, binary_src, 255, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
imshow("3.binary Image", binary_src);
//4、以提取水平和垂直线,作为从图像中分离的结果,但首先让我们初始化的输出图像:
Mat horizontal = binary_src.clone();
Mat vertical = binary_src.clone();
//5、为了提取我们所希望的对象,我们需要创建相应的结构元素。由于这里我们要提取水平线,一个相应的结构元素有以下形状:
int horizontalsize = horizontal.cols / 30;
Mat horizontalStructure = getStructuringElement(MORPH_RECT, Size(horizontalsize,1));
erode(horizontal, horizontal, horizontalStructure, Point(-1, -1));
dilate(horizontal, horizontal, horizontalStructure, Point(-1, -1));
imshow("4.1. horizontal", horizontal);
//6、 垂直线条的的用法也是这样,相应的结构元素如下:
int verticalsize = vertical.rows / 30;
Mat verticalStructure = getStructuringElement(MORPH_RECT, Size( 1,verticalsize));
erode(vertical, vertical, verticalStructure, Point(-1, -1));
dilate(vertical, vertical, verticalStructure, Point(-1, -1));
imshow("4.2. vertical", vertical);
//7、图像的边缘是有点粗糙的。由于这个原因,我们需要光顺处理边缘,以获得更平滑的结果
// Inverse vertical image
bitwise_not(vertical, vertical);
imshow("5. vertical_bit", vertical);
// Extract edges and smooth image according to the logic
// 1. extract edges
// 2. dilate(edges)
// 3. src.copyTo(smooth)
// 4. blur smooth img
// 5. smooth.copyTo(src, edges)
// Step 1
Mat edges;
adaptiveThreshold(vertical, edges, 255, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 3, -2);
imshow("6.1. edges", edges);
// Step 2
Mat kernel = Mat::ones(2, 2, CV_8UC1);
dilate(edges, edges, kernel);
imshow("6.2. dilate", edges);
// Step 3
Mat smooth;
vertical.copyTo(smooth);
// Step 4
blur(smooth, smooth, Size(2, 2));
// Step 5
smooth.copyTo(vertical, edges);
// Show final result
imshow("6.3. smooth", vertical);
waitKey(0);
return 0;
}
运行结果
主要借鉴”Madcola“和”Micheal超“两位大神的文章。两位大神的博客主页是:
https://www.cnblogs.com/skyfsm/(Madcola)
https://blog.csdn.net/qq_42887760(Micheal超)
结束语
由于时间和文章篇幅有限,本次总结先到这里,下次小白会为小伙伴们带来OpenCV的角点检测,各位小伙伴敬请期待。如果小伙伴觉得本文对自己有帮助,请帮忙点击一下右下角的“好看”,鼓励一下小白。
往期文章一览
1、助力2019剩余2/3时光
2、影响机器视觉的场景因素有哪些
3、SLAM实习生面试基础知识总结
4、如何让黑白相片恢复生机
5、我竟然用OpenCV实现了卡尔曼滤波
6、【走进OpenCV】滤波代码原来这么写
7、【走进OpenCV】这样腐蚀下来让我膨胀
8、小心!你看到的图像可能隐藏了重大机密