阈值化 OTSU算法 cvAdaptiveThreshold 函数
来源:互联网 发布:阿里云app服务器价格表 编辑:程序博客网 时间:2024/05/19 09:15
/*
*比较opencv自适应阈值与OTSU自适应阈值的效果
*OTSU有很好的效果,但是加入光照调节之后效果不好,所以取消
*cvAdaptiveThreshold 主要功能是边缘提取,也能自适应二值化(但block_size要设置非常大,并且二值化效果依赖于block_size值)
*cvThreshold 本身能实现OSTU算法, 参考: cvThreshold(src, dst, 0, max_val , CV_THRESH_OTSU)
*Date: 2012/3/20
#include "stdio.h"
#include "stdafx.h"
#include "highgui.h"
#include <cv.h>
#include <cxcore.h>
#include "iostream"
#include "math.h"
#include <ctype.h>
using namespace std;
using namespace cv;
void cvOtsu(IplImage *src, int *thresholdValue, int *thresholdValue_deltaT); //大津发求阈值,deltaT为光照修正后的阈值
int main(int argc, char** argv)
{
//窗口,图像文件初始化
const char* file = "D:\\C++ Projects\\OpenCV_project\\test_img\\right14.jpg";
// const char* file = "D:\\C++ Projects\\OpenCV_project\\test_video\\02.jpg";
const char* woriginal = "original image";
const char* wnormal = "normal threshold";
const char* wotsu = "otsu";
const char* wotsud = "otsu light revise";
const char* wadaptm = "adapt threshold mean"; //均值方法 自适应阈值
const char* wadaptg = "adapt threshold gaussian"; //高斯方法 自适应阈值
cvNamedWindow(woriginal);
cvNamedWindow(wnormal);
cvNamedWindow(wotsu);
cvNamedWindow(wotsud);
cvNamedWindow(wadaptm);
cvNamedWindow(wadaptg);
IplImage* src = cvLoadImage(file); //源图像为三通道.
assert(src != NULL);
IplImage* dst = cvCreateImage(cvSize(src->width/2, src->height/2), src->depth, src->nChannels);
cvResize(src, dst);
assert( dst != NULL);
IplImage* imgsrc = cvCreateImage(cvGetSize(dst), 8,1);
cvCvtColor(dst, imgsrc, CV_BGR2GRAY); //xstring文件 Line1070, return (*this) 报错时, 注意检查图像格式是否符合函数要求
assert(imgsrc != NULL);
IplImage* imgnor = cvCloneImage(imgsrc);
assert(imgnor != NULL);
IplImage* imgotsu = cvCloneImage(imgsrc);
assert(imgotsu != NULL);
IplImage* imgotsud = cvCloneImage(imgsrc);
assert(imgotsud != NULL);
IplImage* imgadaptm = cvCreateImage(cvGetSize(imgsrc), imgsrc->depth, imgsrc->nChannels);
assert(imgadaptm != NULL);
IplImage* imgadaptg = cvCloneImage(imgsrc);
assert(imgadaptg != NULL);
int otsu_threshold = 0;
int otsu_threshold_del =0; //光照调节阈值,效果很不好
double normal_threshold = 150;
double max_val = 255; //阈值化后的最大值
cvOtsu(imgsrc, &otsu_threshold, &otsu_threshold_del); //计算出otsu的阈值
//二进制阈值化
cvThreshold(imgsrc, imgnor, normal_threshold, max_val , CV_THRESH_BINARY); //普通阈值化
// cvThreshold(imgsrc, imgnor, 0, max_val , CV_THRESH_OTSU); //调用OTSU算法的参数设置***
cvThreshold(imgsrc, imgotsu, otsu_threshold, max_val , CV_THRESH_BINARY); //otsu 自适应
cvAdaptiveThreshold(imgsrc, imgadaptm, max_val,0,0,31,5); //自适应均值方法阈值化
cvAdaptiveThreshold(imgsrc, imgadaptg, max_val, 1,0,21,5); //自适应高斯方法阈值化
//对自适应阈值后的图像做闭运算
// cvMorphologyEx(imgotsu,imgotsud,imgadaptg, NULL,CV_MOP_CLOSE);
// cvErode(imgadaptm,imgotsud); //腐蚀明亮区域
// cvDilate(imgadaptm,imgotsud); //膨胀明亮区域
cout << "test message!\n"; //可以输出到屏幕
cvShowImage(woriginal, imgsrc);
cvShowImage(wnormal, imgnor);
cvShowImage(wotsu, imgotsu);
cvShowImage(wotsud, imgotsud);
cvShowImage(wadaptm, imgadaptm);
cvShowImage(wadaptg, imgadaptg);
cvWaitKey();
cvReleaseImage(&imgsrc);
cvDestroyAllWindows();
return 0;
}
/* OTSU大津法
* thresholdValue 为使类间方差最大的阈值
*thresholdValue_deltaT 为 thresholdValue 加上光照修正
*/
void cvOtsu(IplImage *src, int *thresholdValue, int *thresholdValue_deltaT)
{
int deltaT = 0; //光照调节参数
uchar grayflag =1;
IplImage* gray = NULL;
if(src->nChannels != 1) //检查源图像是否为灰度图像
{
gray = cvCreateImage(cvGetSize(src), 8, 1);
cvCvtColor(src, gray, CV_BGR2GRAY);
grayflag = 0;
}
else gray = src;
uchar* ImgData=(uchar*)(gray->imageData);
int thresholdValue_temp = 1;
int ihist[256]; //图像直方图,256个点
int i, imgsize; //循环变量,图像尺寸
int n, n1, n2; //n 非零像素个数, n1 前景像素个数, n2 背景像素个数
double m1, m2, sum, csum, fmax, sb;//m1前景灰度均值,m2背景灰度均值
//对直方图置零
memset(ihist, 0, sizeof(ihist));
//生成直方图
imgsize = (gray->widthStep)*(gray->height);//图像数据总数
for (i=0; i<imgsize;i++)
{
ihist[((int)(*ImgData))&255]++;//灰度统计 '&255'防止指针溢出
ImgData++;//像素遍历
}
// set up everything
sum=csum=0.0;
n=0;
for (i=0; i<255; i++)
{
sum+=(double)i*(double)ihist[i]; // x*f(x)质量矩
n+= ihist[i]; //f(x)质量 像素总数
}
deltaT = (int)(sum/imgsize); //像素平均灰度
deltaT = deltaT>>1; //与之矫正,delatT = v*n; v=0.5
if (!n)
{//图像全黑,输出警告
fprintf (stderr, "NOT NORMAL thresholdValue=160\n");
}
// OTSU算法
fmax=-1.0;
n1=0;
for (i=0; i<255; i++)
{
n1+= ihist[i];
if (n1==0) {continue;}
n2=n-n1;
if (n2==0) {break;}
csum += (double)i *ihist[i];
m1=csum/n1;
m2=(sum-csum)/n2;
sb=(double)n1*(double)n2*(m1-m2)*(m1-m2); //计算类间方差, 公式已简化
if (sb>fmax)
{
fmax=sb;
thresholdValue_temp=i; //找到使类间方差最大的灰度值i
}
}
*thresholdValue = thresholdValue_temp;
*thresholdValue_deltaT = thresholdValue_temp + deltaT;
if(!grayflag) cvReleaseImage(&gray);
}
*比较opencv自适应阈值与OTSU自适应阈值的效果
*OTSU有很好的效果,但是加入光照调节之后效果不好,所以取消
*cvAdaptiveThreshold 主要功能是边缘提取,也能自适应二值化(但block_size要设置非常大,并且二值化效果依赖于block_size值)
*cvThreshold 本身能实现OSTU算法, 参考: cvThreshold(src, dst, 0, max_val , CV_THRESH_OTSU)
*Date: 2012/3/20
*Author: Rocky Chen
* 参考: http://www.opencv.org.cn/forum/viewtopic.php?t=3355
*/#include "stdio.h"
#include "stdafx.h"
#include "highgui.h"
#include <cv.h>
#include <cxcore.h>
#include "iostream"
#include "math.h"
#include <ctype.h>
using namespace std;
using namespace cv;
void cvOtsu(IplImage *src, int *thresholdValue, int *thresholdValue_deltaT); //大津发求阈值,deltaT为光照修正后的阈值
int main(int argc, char** argv)
{
//窗口,图像文件初始化
const char* file = "D:\\C++ Projects\\OpenCV_project\\test_img\\right14.jpg";
// const char* file = "D:\\C++ Projects\\OpenCV_project\\test_video\\02.jpg";
const char* woriginal = "original image";
const char* wnormal = "normal threshold";
const char* wotsu = "otsu";
const char* wotsud = "otsu light revise";
const char* wadaptm = "adapt threshold mean"; //均值方法 自适应阈值
const char* wadaptg = "adapt threshold gaussian"; //高斯方法 自适应阈值
cvNamedWindow(woriginal);
cvNamedWindow(wnormal);
cvNamedWindow(wotsu);
cvNamedWindow(wotsud);
cvNamedWindow(wadaptm);
cvNamedWindow(wadaptg);
IplImage* src = cvLoadImage(file); //源图像为三通道.
assert(src != NULL);
IplImage* dst = cvCreateImage(cvSize(src->width/2, src->height/2), src->depth, src->nChannels);
cvResize(src, dst);
assert( dst != NULL);
IplImage* imgsrc = cvCreateImage(cvGetSize(dst), 8,1);
cvCvtColor(dst, imgsrc, CV_BGR2GRAY); //xstring文件 Line1070, return (*this) 报错时, 注意检查图像格式是否符合函数要求
assert(imgsrc != NULL);
IplImage* imgnor = cvCloneImage(imgsrc);
assert(imgnor != NULL);
IplImage* imgotsu = cvCloneImage(imgsrc);
assert(imgotsu != NULL);
IplImage* imgotsud = cvCloneImage(imgsrc);
assert(imgotsud != NULL);
IplImage* imgadaptm = cvCreateImage(cvGetSize(imgsrc), imgsrc->depth, imgsrc->nChannels);
assert(imgadaptm != NULL);
IplImage* imgadaptg = cvCloneImage(imgsrc);
assert(imgadaptg != NULL);
int otsu_threshold = 0;
int otsu_threshold_del =0; //光照调节阈值,效果很不好
double normal_threshold = 150;
double max_val = 255; //阈值化后的最大值
cvOtsu(imgsrc, &otsu_threshold, &otsu_threshold_del); //计算出otsu的阈值
//二进制阈值化
cvThreshold(imgsrc, imgnor, normal_threshold, max_val , CV_THRESH_BINARY); //普通阈值化
// cvThreshold(imgsrc, imgnor, 0, max_val , CV_THRESH_OTSU); //调用OTSU算法的参数设置***
cvThreshold(imgsrc, imgotsu, otsu_threshold, max_val , CV_THRESH_BINARY); //otsu 自适应
cvAdaptiveThreshold(imgsrc, imgadaptm, max_val,0,0,31,5); //自适应均值方法阈值化
cvAdaptiveThreshold(imgsrc, imgadaptg, max_val, 1,0,21,5); //自适应高斯方法阈值化
//对自适应阈值后的图像做闭运算
// cvMorphologyEx(imgotsu,imgotsud,imgadaptg, NULL,CV_MOP_CLOSE);
// cvErode(imgadaptm,imgotsud); //腐蚀明亮区域
// cvDilate(imgadaptm,imgotsud); //膨胀明亮区域
cout << "test message!\n"; //可以输出到屏幕
cvShowImage(woriginal, imgsrc);
cvShowImage(wnormal, imgnor);
cvShowImage(wotsu, imgotsu);
cvShowImage(wotsud, imgotsud);
cvShowImage(wadaptm, imgadaptm);
cvShowImage(wadaptg, imgadaptg);
cvWaitKey();
cvReleaseImage(&imgsrc);
cvDestroyAllWindows();
return 0;
}
/* OTSU大津法
* thresholdValue 为使类间方差最大的阈值
*thresholdValue_deltaT 为 thresholdValue 加上光照修正
*/
void cvOtsu(IplImage *src, int *thresholdValue, int *thresholdValue_deltaT)
{
int deltaT = 0; //光照调节参数
uchar grayflag =1;
IplImage* gray = NULL;
if(src->nChannels != 1) //检查源图像是否为灰度图像
{
gray = cvCreateImage(cvGetSize(src), 8, 1);
cvCvtColor(src, gray, CV_BGR2GRAY);
grayflag = 0;
}
else gray = src;
uchar* ImgData=(uchar*)(gray->imageData);
int thresholdValue_temp = 1;
int ihist[256]; //图像直方图,256个点
int i, imgsize; //循环变量,图像尺寸
int n, n1, n2; //n 非零像素个数, n1 前景像素个数, n2 背景像素个数
double m1, m2, sum, csum, fmax, sb;//m1前景灰度均值,m2背景灰度均值
//对直方图置零
memset(ihist, 0, sizeof(ihist));
//生成直方图
imgsize = (gray->widthStep)*(gray->height);//图像数据总数
for (i=0; i<imgsize;i++)
{
ihist[((int)(*ImgData))&255]++;//灰度统计 '&255'防止指针溢出
ImgData++;//像素遍历
}
// set up everything
sum=csum=0.0;
n=0;
for (i=0; i<255; i++)
{
sum+=(double)i*(double)ihist[i]; // x*f(x)质量矩
n+= ihist[i]; //f(x)质量 像素总数
}
deltaT = (int)(sum/imgsize); //像素平均灰度
deltaT = deltaT>>1; //与之矫正,delatT = v*n; v=0.5
if (!n)
{//图像全黑,输出警告
fprintf (stderr, "NOT NORMAL thresholdValue=160\n");
}
// OTSU算法
fmax=-1.0;
n1=0;
for (i=0; i<255; i++)
{
n1+= ihist[i];
if (n1==0) {continue;}
n2=n-n1;
if (n2==0) {break;}
csum += (double)i *ihist[i];
m1=csum/n1;
m2=(sum-csum)/n2;
sb=(double)n1*(double)n2*(m1-m2)*(m1-m2); //计算类间方差, 公式已简化
if (sb>fmax)
{
fmax=sb;
thresholdValue_temp=i; //找到使类间方差最大的灰度值i
}
}
*thresholdValue = thresholdValue_temp;
*thresholdValue_deltaT = thresholdValue_temp + deltaT;
if(!grayflag) cvReleaseImage(&gray);
}
- 阈值化 OTSU算法 cvAdaptiveThreshold 函数
- 用otsu算法进行图像阈值化
- Otsu自适应阈值算法
- 图像otsu阈值化
- Otsu阈值化
- OTSU阈值化
- opencv中利用otsu算法进行阈值化
- OpenCV 阈值化操作cvThreshold 和 自适应阈值cvAdaptiveThreshold操作
- opencv 中的Otsu阈值化
- opencv学习笔记(十九)单通道固定阈值cvThreshold()以及自适应阈值化 OTSU算法
- 自动阈值法:Otsu法 用MATLAB实现Otsu算法:
- otsu阈值
- 最大类间差法求阈值(OTSU算法)
- 自适应阈值分割之otsu算法
- 自适应阈值分割之otsu算法
- “学会积累”——Otsu阈值算法
- OTSU算法 -- 三通道阈值分割
- 自适应阈值 cvAdaptiveThreshold
- OK6410_NFS_挂载成功/*嵌入式_学习*/
- CListCtrl使用技巧
- Spring 你让我伤透了个心啊!
- 判断出栈序列是否合法
- CListCtrl应用介绍
- 阈值化 OTSU算法 cvAdaptiveThreshold 函数
- FFmpeg demuxer如何
- Solaris代码调试
- 图解Windows xp—FTP服务器配置
- IT公司面试宝典,全
- scannf的用法
- 常用的排序算法分析
- 我的编程生活-20120320
- 关于Android 数据库SQLite性能优化