opencv入门_【OpenCV入门之十八】通过形态学操作提取水平与垂直线

a8da981b89c9dba3005d914ad9a0a019.png

小白导读

学习计算机视觉最重要的能力应该就是编程了,为了帮助小伙伴尽快入门计算机视觉,小白准备了【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

5931174527051d28f1af57dfc69a1ebb.png

一个像素宽的垂直线——垂直长度width/30

25f81e4383e2e46d9c9498bfcaf47f7b.png

  • 开操作 (腐蚀+膨胀)提取 水平与垂直线

程序代码

#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;
}

运行结果

aa6c721fe811dc36b2242f00fdbe18aa.png

主要借鉴”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、小心!你看到的图像可能隐藏了重大机密

d37a48c943a39bd5da605f6d52ae1b92.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值