二值图的定义

二值图是一种特殊的灰度图,即每个像素点要么是白(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. Swift 4 关于Darwin这个Module

    大家在做app或者framework的时候经常会用到生成随机数的方法arc4random系列,或者取绝对值abs()等.所以我有一次好奇的想看看在Developer Document里 是怎么描述这些 ...

  2. Android防止手动添加的本地库文件被NDK工具清理掉

    比如要添加一个名为libocr的本地库,先将libocr.so文件拷贝到jni目录下,然后在Android.mk文件中添加以下语句即可. 例: LOCAL_PATH := $(call my-dir) ...

  3. Debian Security Advisory DSA-4421-1 chromium security update

    Debian Security Advisory DSA-4421-1 chromium security update Package        : chromiumCVE ID         ...

  4. 大受喜欢安卓触控一体机连接云端数据化管理提供例程DEMO

    1.首先,安卓系统坚持了它的开放性,为消费者和开发者同时留出了空间.这是安卓能够快速成长的关键因素.在安卓之前,没有任何一个智能操作系统的开源程度能够像安卓一样.免费开源的安卓系统节约了版权费用. 2 ...

  5. JAVA进阶15

    间歇性混吃等死,持续性踌躇满志系列-------------第15天 1.TCP网络程序 package code0329; import java.io.BufferedReader; import ...

  6. SVM小白教程(2):拉格朗日对偶

    在上一篇文章中,我们推导出了 SVM 的目标函数: \[ \underset{(\mathbf{w},b)}{\operatorname{min}} ||\mathbf{w}|| \\ \operat ...

  7. mac配置go使用gopm下载第三方包

    打开zshrc文件 vim ~/.zshrc 输入变量 export GOPATH="/Users/chennan/go" #这个自定义 export GOBIN=$GOPATH/ ...

  8. 如何使用Linux的Crontab定时执行PHP脚本的方法[转载]

    首先说说cron,它是一个linux下的定时执行工具.根用户以外的用户可以使用 crontab 工具来配置 cron 任务.所有用户定义的 crontab 都被保存在/var/spool/cron 目 ...

  9. Hutool工具里,POST方法,body中传参的几种调用方法

    接口说明: POSTMAN测试: JAVA代码: package com.provy.guard.api; import java.util.HashMap; import java.util.Map ...

  10. kafka 重新分配partition

    登陆kafka manager 进入相关topic 点击generate partition assignments 点击reassign partirons