查看OpenCV文档cvThreshold(),在二值化函数cvThreshold(const CvArr* src, CvArr* dst, double threshold, double max_value, int threshold_type)中,参数threshold_type有5种类型:

  • THRESH_BINARY
  • THRESH_BINARY_INV
  • THRESH_TRUNC
  • THRESH_TOZERO
  • THRESH_TOZERO_INV

问题来了:为什么可以在threshold_type参数中使用CV_THRESH_OTSU,在哪里可以查看这种OTSU,它用的什么方法?经多次验证,二值化的效果很好,且速度很快。
已经有一些同志在使用:
例证1:例证1
例证2:例证2
例证3:例证3

我的遭遇:为了二值化一个比较大的图像(10M,3840*2748),痛苦的看了各种论文,尝试了各种的二值化方法:一维OTSU,快速迭代的一维OTSU,二维的OTSU,快速迭代的二维OTSU。但现实的残酷的!只有二维的OTSU和快速迭代的OTSU可用,但前者处理时间让人难以接受,后者也要500多个ms。        快速迭代的二维OTSU算法是根据吴一全老师的《二维最大类间方差阈值分割的快速迭代算法》(论文下载链接,提取码:fd0b)来实现的。但是令我哭笑不得的是,无意中在网上发现了一种方法threshold_type使用参数使用CV_THRESH_OTSU时,时间却大大的缩短。程序如下(
程序下载链接提取码:fd0b),图像下载  (提取码:24f3)。

/* otsu_2d:二维最大类间方差阈值分割的快速迭代算法   吴一全 */
#include <iostream>
#include <cv.h>
#include <highgui.h> using namespace std;
double TwoDimentionOtsu(IplImage *image);
int main()
{
IplImage* srcImage = cvLoadImage( "E:/image_1/14.bmp", );
assert(NULL != srcImage); cvNamedWindow("src",);
cvShowImage("src",srcImage); clock_t start_time=clock(); //计算最佳阈值
double threshold = TwoDimentionOtsu(srcImage);//70,125 clock_t end_time=clock();
cout<< "Running time is: "<<static_cast<double>(end_time-start_time)/CLOCKS_PER_SEC*<<"ms"<<endl;//输出运行时间 cout << "threshold=" << threshold << endl; IplImage* biImage = cvCreateImage(cvGetSize(srcImage),,);
//对图像二值化
//cvThreshold(srcImage,biImage,255,255, CV_THRESH_OTSU | CV_THRESH_BINARY);
cvThreshold(srcImage,biImage,threshold,, CV_THRESH_BINARY); cvNamedWindow("binary",);
cvShowImage("binary",biImage); cvWaitKey(); cvReleaseImage(&srcImage);
cvReleaseImage(&biImage); cvDestroyAllWindows(); return ;
}
double TwoDimentionOtsu(IplImage *image)
{
double t0 = , s0 = , t = , s = ;
int width = image->width;
int height = image->height;
double dHistogram[][]={0.0}; //建立二维灰度直方图
unsigned long sum0 = ,sum1 = ; //sum0记录所有的像素值的总和,sum1记录3x3窗口的均值的总和
uchar* data = (uchar*)image->imageData;
for(int i=; i<height; i++)
{
for(int j=; j<width; j++)
{
unsigned char nData1 = data[i * image->widthStep + j];//nData1记录当前点(i,j)的像素值
sum0 += nData1;
unsigned char nData2 = ; //nData2记录以当前点(i,j)为中心三领域像素值的平均值
int nData3 = ; //nData3记录以当前点(i,j)为中心三领域像素值之和,注意9个值相加可能超过一个字节
for(int m=i-; m<=i+; m++)
{
for(int n=j-; n<=j+; n++)
{
if((m>=)&&(m<height)&&(n>=)&&(n<width))
nData3 += data[m * image->widthStep + n];
}
}
nData2 = (unsigned char)(nData3/); //对于越界的索引值进行补零,邻域均值
sum1 += nData2;
dHistogram[nData1][nData2]++;
}
} long N = height*width; //总像素数
t = sum0/N; //图像灰度级均值
s = sum1/N; //邻域平均灰度级的均值 s0 = s;
t0 = t;
for(int j=; j<; j++)
for(int i=; i<; i++)
{
dHistogram[i][j] = dHistogram[i][j]/N; //得到归一化的概率分布
} double w0 = 0.0,w1 = 0.0,u0i = 0.0,u1i = 0.0,u0j = 0.0,u1j = 0.0; do
{
t0 = t;
s0 = s;
w0 = w1 = u0i = u1i = u0j = u1j = 0.0;
for (int i = ,j; i < ; i++)
{
for (j = ; j < s0; j++)
{
w0 += dHistogram[i][j];
u0j += dHistogram[i][j] * j;
} for (; j < ; j++)
{
w1 += dHistogram[i][j];
u1j += dHistogram[i][j] * j;
} }
for (int j = ,i = ; j < ; j++)
{
for (i = ; i < t0; i++)
u0i += dHistogram[i][j] * i;
for (; i < ; i++)
u1i += dHistogram[i][j] * i;
}
u0i /= w0;
u1i /= w1 ;
u0j /= w0;
u1j /= w1; t = (u0i + u1i)/;
s = (u0j + u1j)/;
}while ( t != t0);//是否可以用这个做为判断条件,有待考究,请高手指点 return t;//只用t做为阈值,个人也感觉不妥,但没有找到更好的方法,请高手指点 }

输出结果:

 cvThreshold()参数设为CV_THRESH_OTSU,输入结果:

二值化函数cvThreshold()参数CV_THRESH_OTSU的疑惑【转】的更多相关文章

  1. Win8MetroC#数字图像处理--2.2图像二值化函数

    原文:Win8MetroC#数字图像处理--2.2图像二值化函数 [函数代码] /// <summary> /// Binary process. /// </summary> ...

  2. opencv-python图像二值化函数cv2.threshold函数详解及参数cv2.THRESH_OTSU使用

    cv2.threshold()函数的作用是将一幅灰度图二值化,基本用法如下: #ret:暂时就认为是设定的thresh阈值,mask:二值化的图像 ret,mask = cv2.threshold(i ...

  3. OpenCV图像的全局阈值二值化函数(OTSU)

    cv::threshold(GrayImg, Bw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);//灰度图像二值化 CV_THRESH_OTSU是提取图像最 ...

  4. 【转载】opencv 二值化函数——cv2.threshold

    https://blog.csdn.net/weixin_38570251/article/details/82079080 threshold:固定阈值二值化, ret, dst = cv2.thr ...

  5. MATLAB实现二值化函数

    function  bc = binary_conversion(a)  %这是灰度值二值化转换函数,阈值为平均值j=imread(a);             %读取灰度图像   j=double ...

  6. python的N个小功能(图片预处理:打开图片,滤波器,增强,灰度图转换,去噪,二值化,切割,保存)

    ############################################################################################# ###### ...

  7. 【转】Emgu CV on C# (五) —— Emgu CV on 局部自适应阈值二值化

    局部自适应阈值二值化 相对全局阈值二值化,自然就有局部自适应阈值二值化,本文利用Emgu CV实现局部自适应阈值二值化算法,并通过调节block大小,实现图像的边缘检测. 一.理论概述(转载自< ...

  8. [转载+原创]Emgu CV on C# (五) —— Emgu CV on 局部自适应阈值二值化

    局部自适应阈值二值化 相对全局阈值二值化,自然就有局部自适应阈值二值化,本文利用Emgu CV实现局部自适应阈值二值化算法,并通过调节block大小,实现图像的边缘检测. 一.理论概述(转载自< ...

  9. python实现图像二值化

    1.什么是图像二值化 彩色图像: 有blue,green,red三个通道,取值范围均为0-255 灰度图:只有一个通道0-255,所以一共有256种颜色 二值图像:只有两种颜色,黑色和白色,二值化就是 ...

随机推荐

  1. gitlab的docker安装,非标准端口,如何处理?

    这个问题的定义是: 如果我们不是用的80端口对外提供服务, 但gitlab的docker容器里的nginx却是80端口, 那么,在我们clone代码时,带的Http地址也会是80端口,这显然会出现问题 ...

  2. webpack 模块标识符(Module Identifiers)

    让我们向项目中再添加一个模块 print.js: project webpack-demo |- package.json |- webpack.config.js |- /dist |- /src ...

  3. 3237: [Ahoi2013]连通图 线段树分治

    题解: cf765f cf671e bzoj4184 bzoj4552 线段树分治裸题 还是介绍一下线段树分治 这个东西其实挺简单但也挺有用的 可以把删除+插入操作变成只有插入(倒着就是删除) 像这一 ...

  4. A. 【UNR #2】积劳成疾

    链接:http://uoj.ac/contest/40/problem/311 题解: 一道很好的期望题吧 用dp的老思路,枚举最大值将序列分割 想到这个就很简单了 状态f[i][j]表示前i个,最大 ...

  5. day9--队列queue

    queue队列 Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递.一个线程放入数据,另外 ...

  6. 【Java】 剑指offer(59-1) 滑动窗口的最大值

      本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值.例 ...

  7. Android 之 <requestFocus />

    EditText中的 <requestFocus />标记?? 第一个<requestFocus />会获得焦点,意思就是如果你给某个edittext设置了<reques ...

  8. 不一样的go语言-构建系统与构件系统

    前言   代码的最后一步是构建成计算机可识别的二进制数据,然后才得以在计算机上运行.如果你曾经写过有点规模(至少数十个以上独立的源文件,且需要依赖第三方包)C语言项目,必定对C语言项目的构建过程印象深 ...

  9. centOS7升级git版本到2.7.3

    CentOS 自带的git版本太低,需要升级到2.1.2版本以上才能使用gitea. 升级方法: 1.安装所需软件包 yum install curl-devel expat-devel gettex ...

  10. C语言---斐波那契问题

      最近学习了一个叫递归的概念,里面最著名的一个例子就是斐波那契问题,觉得很有意思,就来实现一下: 什么是斐波那契数列   斐波那契数列,又称黄金分割数列,值得这样一个数列:0.1.1.3.5.8.1 ...