二值图的定义

二值图是一种特殊的灰度图,即每个像素点要么是白(0),要么是黑(255)

无论是灰度图还是二值图都是用阈值化的知识。

二值图的应用

图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。

阈值化

二值化只是阈值化的一个特例。

阈值化就是设定一个阈值,使超过或者低于该阈值的像素变成某一个给定值。

二值化/阈值化方法

1,无脑简单判断

通过搜索灰度图每个像素,判断灰度值是否大于127 [(255+0)/2 = 127.5]

//二值化 一

#include<opencv2/highgui/highgui.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp> using namespace cv; int main()
{
Mat srcImage = imread("images/favorite/Lena.jpg", 0);
Mat dstImage; srcImage.copyTo(dstImage); int rows = srcImage.rows;
int cols = srcImage.cols * srcImage.channels(); for(int i = 0; i < rows; i++)
{
uchar* data = dstImage.ptr<uchar>(i);
for(int j = 0; j < cols; j++)
{
if(data[j] > 127)
data[j] = 255;
else
data[j] = 0;
} }
imshow("Lena", dstImage); waitKey(30000);
return 0;
}

opencv3函数threshold()实现

threshold是阈值化方法,也可以大材小用一下做二值化。

在imgproc.hpp中可以看到形参

//看函数参数
//CV_EXPORTS_W 就是double CV_EXPORTS_W double threshold(
InputArray src, //第一个参数表示输入图像,必须为单通道灰度图。
OutputArray dst, //第二个参数表示输出图像,为单通道黑白图。
double thresh, //第三个参数表示阈值,例如127
double maxval, //第四个参数表示最大值,例如255
int type //第五个参数表示运算方法。
);

在OpenCV的imgproc\types_c.h中可以找到运算方法的定义。

/** Threshold types */
enum
{
CV_THRESH_BINARY =0, /**< value = value > threshold ? max_value : 0 */
CV_THRESH_BINARY_INV =1, /**< value = value > threshold ? 0 : max_value */
CV_THRESH_TRUNC =2, /**< value = value > threshold ? threshold : value */
CV_THRESH_TOZERO =3, /**< value = value > threshold ? value : 0 */
CV_THRESH_TOZERO_INV =4, /**< value = value > threshold ? 0 : value */
CV_THRESH_MASK =7,
CV_THRESH_OTSU =8, /**< use Otsu algorithm to choose the optimal threshold value;
combine the flag with one of the above CV_THRESH_* values */
CV_THRESH_TRIANGLE =16 /**< use Triangle algorithm to choose the optimal threshold value;
combine the flag with one of the above CV_THRESH_* values, but not
with CV_THRESH_OTSU */
};

实例:

#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/core/core.hpp> using namespace cv; int main()
{
Mat srcImage = imread("images/favorite/Lena.jpg", 0);
Mat dstImage; threshold(srcImage, dstImage, 127, 255, 0); imshow("Lena", dstImage); waitKey(30000);
return 0;
}

2,Otsu算法(大律法或最大类间方差法)

大津法由大津(日本学者,名叫OTSU)于1979年提出,对图像Image,记t为前景与背景的分割阈值,前景点数占图像比例为w0,平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1。图像的总平均灰度为:\(u=w0*u0+w1*u1\)。

我们的目标是从最小灰度值到最大灰度值找到一个合适的分隔值t(即阈值),遍历\(t\),当\(t\)使得值\(g=w0*(u0-u)^2+w1*(u1-u)^2\)最大时t即为分割的最佳阈值。对大津法可作如下理解:该式实际上就是类间方差值,阈值t分割出的前景和背景两部分构成了整幅图像,而前景取值u0,概率为 w0,背景取值u1,概率为w1,总均值为u,根据方差的定义即得该式。

因方差是灰度分布均匀性的一种度量,方差值越大,说明构成图像的两部分差别越大, 当部分目标错分为背景或部分背景错分为目标都会导致两部分差别变小,因此使类间方差最大的分割意味着错分概率最小。

直接应用大津法计算量较大,因此我们在实现时采用了等价的公式\(g=w0*w1*(u0-u1)^2\)。(把u代入g得到)

OpenCV3 纯代码实现大津法

#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio> using namespace std;
using namespace cv; int main()
{
Mat src = imread("images/favorite/Lena.jpg", 0);
Mat dst; int best_t = 1;
long long best_g = 0; for(int t = 1; t < 255; t++)
{
int u0 = 0;
int u1 = 0; int num_of_u0 = 0;
int num_of_u1 = 0;
long long sum_of_u0 = 0;
long long sum_of_u1 = 0; for (int i = 0; i < src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
int pixel = src.at<uchar>(i, j);
if(pixel >= t)
{
num_of_u0++;
sum_of_u0+=pixel;
}
else
{
num_of_u1++;
sum_of_u1+=pixel;
}
}
} if(num_of_u0 == 0 || num_of_u1 == 0)
continue; u0 = sum_of_u0/num_of_u0;
u1 = sum_of_u1/num_of_u1; long long g = num_of_u0*num_of_u1/(src.rows*src.cols)*(u1-u0)*(u1-u0);
// long long g = num_of_u0/(src.rows*src.cols)*num_of_u1/(src.rows*src.cols)*(u1-u0)*(u1-u0);精度太低,全是0
// long long g = num_of_u0*num_of_u1*(u1-u0)*(u1-u0);精度太高,容易产生误差 if(g > best_g)
{
best_g = g;
best_t = t;
}
} printf("best_g:%d\nbest_t:%d\n", best_g, best_t); threshold(src, dst, best_t, 255, 0); imshow("Lena0", dst); waitKey(0);
return 0;
}

当然你可以基于直方图,这样只需要遍历0-255像素就ok了。

OpenCV3 threshold算法调用Otsu阈值化

#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio> using namespace std;
using namespace cv; int main()
{
Mat src = imread("images/favorite/Lena.jpg", 0);
Mat dst; threshold(src, dst, 100, 127, THRESH_OTSU); imshow("Lena0", dst);
waitKey(0); return 0;
}

经过实验我们可以得到:当thresholdType为THRESH_OTSU时,thresh参数没有用了。

改进版本

OTSU 算法可以说是自适应计算单阈值(用来转换灰度图像为二值图像)的简单高效方法。下面的代码最早由 Ryan Dibble提供,此后经过多人Joerg.Schulenburg, R.Z.Liu 等修改,补正。

算法对输入的灰度图像的直方图进行分析,将直方图分成两个部分,使得两部分之间的距离最大。划分点就是求得的阈值。

OpenCV3函数adaptiveThreshold实现自适应阈值

在imgproc.hpp中找到adaptiveThreshold的形参

CV_EXPORTS_W void adaptiveThreshold(
InputArray src, //输入图像
OutputArray dst, //输出图像
double maxValue, //最大值,一般为255
int adaptiveMethod, //0或1
int thresholdType,
int blockSize, //bxb区域,必须奇数
double C //减去的常量
);
adaptiveMethod参数 效果
ADAPTIVE_THRESH_MEAN_C bxb区域平均值-C
ADAPTIVE_THRESH_GAUSSIAN_C bxb区域高斯加权平均值-C
#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio> using namespace std;
using namespace cv; int main()
{
Mat src = imread("images/favorite/Lena.jpg", 0);
Mat dst0, dst1; adaptiveThreshold(src, dst0, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 41, 0.0);
adaptiveThreshold(src, dst1, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 41, 0.0); imshow("src", src);
imshow("mean", dst0);
imshow("gaussian", dst1); waitKey(0);
return 0;
}

S0.4 二值图与阈值化的更多相关文章

  1. opencv删除二值图中较小的噪点色块

    CvSeq* contour = NULL; double minarea = 100.0; double tmparea = 0.0; CFileDialog dlg(true); if (dlg. ...

  2. 用 Python 通过马尔可夫随机场(MRF)与 Ising Model 进行二值图降噪

    前言 这个降噪的模型来自 Christopher M. Bishop 的 Pattern Recognition And Machine Learning (就是神书 PRML……),问题是如何对一个 ...

  3. c语言实现灰度图转换为二值图

    将上篇得到的灰度图转换为二值图,读取像素数据,低于某一值置0,否则设置为255,为得到更好的效果不同图片应采用不同的值 /* 2015年6月2日11:16:22 灰度图转换为二值图 blog:http ...

  4. 使用OpenCV查找二值图中最大连通区域

    http://blog.csdn.net/shaoxiaohu1/article/details/40272875 使用OpenCV查找二值图中最大连通区域 标签: OpenCVfindCoutour ...

  5. C语言实现将彩色BMP位图转化为二值图

    CTF做了图片的隐写题,还没有形成系统的认识,先来总结一下BMP图的组成,并通过将彩色图转为二值图的例子加深下理解. 只写了位图二进制文件的格式和代码实现,至于诸如RGB色彩和调色板是什么的一些概念就 ...

  6. zw·准专利·高保真二值图细部切分算法

    zw·准专利·高保真二值图细部切分算法     高保真二值图细部切分算法,是中国字体协会项目的衍生作品.     说准专利算法,是因为对于图像算法的标准不了解,虽然报过专利,但不是这方面的,需要咨询专 ...

  7. coco数据集标注图转为二值图python(附代码)

    coco数据集大概有8w张以上的图片,而且每幅图都有精确的边缘mask标注. 后面后分享一个labelme标注的json或xml格式转二值图的源码(以备以后使用) 而我现在在研究显著性目标检测,需要的 ...

  8. 超越OpenCV速度的MorphologyEx函数实现(特别是对于二值图,速度是CV的4倍左右)。

    最近研究了一下opencv的 MorphologyEx这个函数的替代功能, 他主要的特点是支持任意形状的腐蚀膨胀,对于灰度图,速度基本和CV的一致,但是 CV没有针对二值图做特殊处理,因此,这个函数对 ...

  9. BMP彩色转成黑色二值图

    一天半把彩色bmp转成黑白了. 原理是: 第一步:读出位图数据的偏移位置:即第11个字节,用fseek即可. 然后将偏移位置之前的数据全部写入新的bmp图中. 第二步:用fseek移到位图数据这前,判 ...

随机推荐

  1. 1、jQuery的使用入门

    一.创建一个WEB项目,在WebRoot下新建一个Jscript文件夹,并将jQuery中的jquery-3.1.1.min.js文件复制过来. 二.用<script>标签引入jQuery ...

  2. react动态路由以及获取动态路由

    业务中会遇到点击列表跳转到详情页, 1.在index.js修改我们的跟组件 新建router2的文件 import React from 'react' import { HashRouter as ...

  3. c语言int型和char型的自动类型转换

    ; //机器码为0xff unsigned ; //机器码0xfe if (a <= b){ printf("a <= b\n"); } else{ printf(&q ...

  4. mint-ui Picker设置指定初始值

    最近做的项目公司需求是信息输入页设置地址跳转下一页后,再返回信息输入页查看信息时,地址要默认显示前面选择的地址,以此记录下,需要小伙伴可以看看 data{return{}}中设置   :slots 在 ...

  5. JAVA进阶17

    ---恢复内容开始--- 间歇性混吃等死,持续性踌躇满志系列-------------第17天 1.递归结构 递归是一种常见的解决问题的方法,即把问题逐渐简单化.递归的基本思想就是自己就是“自己调用自 ...

  6. [系统集成] RT(Request Tracker)执行自定义脚本及发送微信、短信的实现方法

    RT(Request Tracker)是一个基于 Perl 语言的开源状态跟踪和工作流系统,支持审批.权限管理等功能,中文化支持的也不错,可以作为企业的流程审批系统使用.可惜的是,该系统在国内使用的不 ...

  7. $HOME

    Ubuntu中 命令行输入$HOME bash: /home/XXX: Is a directory $HOME 是用户主目录

  8. 论文笔记:Fast(er) RCNN

    在 RCNN 初步试水取得成功后,研究人员又迅速跟进,针对 RCNN 中的几点不足提出改进,接连推出了 fast-rcnn 和 faster-rcnn.关于这两篇论文,网上相关的文章实在是多如牛毛,因 ...

  9. java 新手必看大全

    背景:c#开发人员 学习java 新手一枚.只适合新手 1:配置java环境 (win10环境参考本目录java环境配置) 2:IDEA 熟悉开发工具 (当初没学java 很大的一个原因就是工具e文 ...

  10. 微软推荐的.net命名规范

    许多命名约定都与标识符的大小写有关.值得注意的是,公共语言运行库 (CLR) 支持区分大小写和不区分大小写的语言.本主题中描述的大小写约定可帮助开发人员理解和使用库. 大小写样式 下列术语描述了标识符 ...