opencv自适应二值化

  • 前言
  • 一、二值化是什么?
  • 二、自适应二值化
    • 1.为什么要用自适应二值化
    • 2.自适应二值化代码实现(c++)

前言

最近在工作中,要实现自动绘制ROI的功能,但是在代码实现的过程中,遇到了不小的问题,现已解决。


一、二值化是什么?

图像的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。
二值化是图像分割的一种最简单的方法。二值化可以把灰度图像转换成二值图像。把大于某个临界灰度值的像素灰度设为灰度极大值,把小于这个值的像素灰度设为灰度极小值,从而实现二值化。
根据阈值选取的不同,二值化的算法分为固定阈值和自适应阈值。

二、自适应二值化

1.为什么要用自适应二值化

在处理从一个视频流中获取的图片时,往往因为光线的变化,而导致固定的阈值不适用,这样就会导致图片处理的结果大打折扣,现做如下比较:
原图_1:

在图中我们可以看到,只有这个水杯我们希望是黑色的,背景应该处理成白色。那么进行如下不同阈值的尝试。
阈值_100:

 cvtColor(srcClone, srcClone, CV_BGR2GRAY);threshold(srcClone, srcClone, 100, 255, CV_THRESH_BINARY);cv::imwrite("D:/阈值_100.jpg", srcClone);


阈值_110:

 cvtColor(srcClone, srcClone, CV_BGR2GRAY);threshold(srcClone, srcClone, 110, 255, CV_THRESH_BINARY);cv::imwrite("D:/阈值_110.jpg", srcClone);

阈值_120:

 cvtColor(srcClone, srcClone, CV_BGR2GRAY);threshold(srcClone, srcClone, 120, 255, CV_THRESH_BINARY);cv::imwrite("D:/阈值_120.jpg", srcClone);


还是同样的环境(拍摄角度改变了,但还是这个水杯),改变亮度,再来看这个水杯:
原图_2:

阈值_50:

 cvtColor(srcClone, srcClone, CV_BGR2GRAY);threshold(srcClone, srcClone, 50, 255, CV_THRESH_BINARY);cv::imwrite("D:/阈值_50.jpg", srcClone);

阈值_100:

 cvtColor(srcClone, srcClone, CV_BGR2GRAY);threshold(srcClone, srcClone, 100, 255, CV_THRESH_BINARY);cv::imwrite("D:/阈值_100.jpg", srcClone);

很明显可以看到,对于亮度改变的原图_2,原先的阈值_100已经不能完全适用,如果将阈值提升到110甚至再往上就会出现大面积黑色的结果,这就是要使用自适应二值化的原因,可以明显降低亮度变化带来的影响(当然不仅仅用于处理亮度变化)。
接下来看看自适应二值化的结果:
原图_1的自适应二值化:

原图_2的自适应二值化:

从以上结果我们可以看出,对于不同亮度的图片,使用自适应二值化后的结果是相差不大的,但是将两种不同的二值化结果相比较可得出,当背景没有过多的影子以及整张图的亮度没有明显变化(比如从左到右变暗)时,自适应二值化后的结果不一定比得过参数调好的固定阈值二值化,这是因为背景光源信息过于简单(大智若愚),但在处理视频流信息的时候,背景光源总会发生不可控的变化,我们肯定不能每次都通过人工来调整阈值,这是不符合自动化工艺的,因此就要使用一个比较好的自适应二值化。
再给出一个例子:

自适应二值化结果:

在这里就不浪费篇幅与固定阈值二值化做比较,读者可自行比较(本人已经试过,效果没那么好)。

2.自适应二值化代码实现(c++)

void thresholdIntegral(cv::Mat &inputMat, cv::Mat &outputMat)
{// accept only char type matricesCV_Assert(!inputMat.empty());CV_Assert(inputMat.depth() == CV_8U);CV_Assert(inputMat.channels() == 1);CV_Assert(!outputMat.empty());CV_Assert(outputMat.depth() == CV_8U);CV_Assert(outputMat.channels() == 1);// rows -> height -> yint nRows = inputMat.rows;// cols -> width -> xint nCols = inputMat.cols;// create the integral imagecv::Mat sumMat;cv::integral(inputMat, sumMat);CV_Assert(sumMat.depth() == CV_32S);CV_Assert(sizeof(int) == 4);int S = MAX(nRows, nCols)/8;double T = 0.15;// perform thresholdingint s2 = S/2;int x1, y1, x2, y2, count, sum;// CV_Assert(sizeof(int) == 4);int *p_y1, *p_y2;uchar *p_inputMat, *p_outputMat;for( int i = 0; i < nRows; ++i){y1 = i-s2;y2 = i+s2;if (y1 < 0){y1 = 0;}if (y2 >= nRows) {y2 = nRows-1;}p_y1 = sumMat.ptr<int>(y1);p_y2 = sumMat.ptr<int>(y2);p_inputMat = inputMat.ptr<uchar>(i);p_outputMat = outputMat.ptr<uchar>(i);for ( int j = 0; j < nCols; ++j){// set the SxS regionx1 = j-s2;x2 = j+s2;if (x1 < 0) {x1 = 0;}if (x2 >= nCols) {x2 = nCols-1;}count = (x2-x1)*(y2-y1);// I(x,y)=s(x2,y2)-s(x1,y2)-s(x2,y1)+s(x1,x1)sum = p_y2[x2] - p_y1[x2] - p_y2[x1] + p_y1[x1];if ((int)(p_inputMat[j] * count) < (int)(sum*(1.0-T)))p_outputMat[j] = 255;elsep_outputMat[j] = 0;}}
}
---
参考自:[添加链接描述](https://www.cnblogs.com/polly333/p/7269153.html)
这套算法以W*W为模板的矩形区域的二维平滑值来代替一维加权值,从而抛开了一维平滑的方向性问题,是Wellner 自适应滤波阈值的升级版。
若有人对算法原理感兴趣或对源码中有不理解的部分可移步下一篇博客,其中会根据自己的理解进行详细介绍。
本文如有问题请积极指出,万分感谢。

opencv自适应二值化的应用相关推荐

  1. opencv自适应二值化原理

    opencv自适应二值化原理 先对图像做模糊处理(一般是均值或者高斯模糊).(这里可以加上自己的操作,做一些其他类型的模糊以及一些形态学的操作). 用原图与模糊处理之后的图像做差得到一幅图像. 判断图 ...

  2. OpenCV自适应二值化

    关于直方图的理解:http://blog.csdn.net/sheldonwxp/article/details/7693541 //全局自适应方法 double threshold( InputAr ...

  3. 利用python opencv实现图像自适应二值化

    对灰度图像利用阈值得到一个二值化的图像,是常最常用的图像处理技术之一.例如,灰度大于127的图像设置为1.小于127的设置为0,这种处理便是固定阈值127的二值化处理. 自适应的二值化处理不同于固定阈 ...

  4. python3 opencv 基于二值化图像素投影的图片切割方法

    对于一些背景纯色,结构相对简单的图,可以利用传统的opencv图像处理进行分割.先来记录一下基于二值化图像素投影的图片切割方法的实现.比如下面这张图,可以利用这个算法进行切割.(源代码在最后面) 切割 ...

  5. opencv 二值化 python_Python OpenCV 图像二值化-阈值分割

    1.二值化处理 # 手动二值化处理 # 设置阈值大小 threshold thresh = 125 # 设置超过阈值像素值的最大值 maxval = 255 # THRESH_BINARY:超过阈值为 ...

  6. input自适应_【正点原子FPGA连载】第十一章基于OV5640的自适应二值化实验-领航者ZYNQ之HLS 开发指南...

    1)摘自[正点原子]领航者ZYNQ之HLS 开发指南 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手 ...

  7. OpenCV差分二值化的实时场景文本检测的实例(附完整代码)

    OpenCV差分二值化的实时场景文本检测的实例 OpenCV差分二值化的实时场景文本检测的实例 OpenCV差分二值化的实时场景文本检测的实例 OpenCV差分二值化的实时场景文本检测的实例(附完整代 ...

  8. vc++数字图像处理 自适应二值化程序

    这段时间做图像处理,这是用迭代法求阈值的,自适应二值化代码,贴出来希望对大家有帮助 void GrayTrans::Binary() { long i,j; unsigned char pixel; ...

  9. OpenCV图像二值化,Python

    OpenCV图像二值化,Python 原图: 二值化处理(只有黑和白): import cv2if __name__=="__main__":image = cv2.imread( ...

  10. OpenCV二值化cvThreshold和自适应二值化cvAdaptiveThreshold及Otsu

    阈值化函数: double cvThreshold(constCvArr* src, CvArr* dst, double threshold, double max_value,int thresh ...

最新文章

  1. 【TypeScript】探索 var 和 let 关键字之间的差异
  2. 第九天2017/04/18(3、重载/覆盖 PK 重写/重定义、父类子类混搭风、抽象类)
  3. k-d tree算法
  4. Django框架搭建
  5. Oracle简单建立表空间
  6. PAT乙级1006 换个格式输出整数
  7. ipsec加密技术谁提出的_如何提出技术问题以获得高质量的答案
  8. 谷歌查询mysql,谷歌地图:使用mysql查询更新标记不起作用
  9. AudioServicesPlaySystemSound
  10. Git的一些必备用法
  11. 利用junit对springMVC的Controller进行测试
  12. EasyRecovery解救打工人的崩溃
  13. Android修改PackageInstaller自动安装指定应用,android开发网易新闻
  14. easyui主界面布局easyui-layout用法一例
  15. XtraReport报表入库单数字转中文大写数字
  16. WinForm控件Chart的图表类型
  17. VS开发Qt应用时遇到“找不到VCRUNTIME140D_APP.dIl,无法继续执行代码”的错误
  18. 5347 Problem D 数列-训练套题T10T3
  19. 一个正整数 n ,求n!的末尾有几个0
  20. 三星s5html查看器,三星S5玩机技巧之系统精简篇

热门文章

  1. css字体向下来电,css系列之关于字体的事
  2. 机器学习笔记 - 使用Keras + Unet 进行图像分割
  3. ibm澳州业务_通过集体学习使业务用户能够使用IBM Blueworks Live和IBM Industry Models进行业务建模
  4. 使用ADB启动手机APP
  5. qq透明图像问题#13
  6. Java开发求职总结
  7. oracle可视化操作界面——plsql dev安装配置与使用
  8. 如何在物联网低代码平台中使用数据字典功能?
  9. 多组测试数据01字典树「模板」
  10. Linux镜像模式,Linux实现HiTool的合并镜像功能