【拜小白opencv】25-综合示例——8种阈值化操作【OTSU阈值化、自适应阈值化、二进制阈值化、反二进制阈值化、截断阈值化、阈值化为0、反阈值化为0,双阈值化】
来源:互联网 发布:it cost 编辑:程序博客网 时间:2024/06/14 12:18
常言道“温故而知新”,写此文章就是对自己目前学习内容的小小的总结与记录。
本文力求用最简洁的语言,详细的代码将此部分内容讲解清楚,但由于博主同样是刚刚接触OpenCV,或许表达上有些瑕疵,还望读者能够指教探讨,大家共同进步。
博主机器配置为:VS2013+opencv2.4.13+Win-64bit。
若本文能给读者带来一点点启示与帮助,我就很开心了。
===========================分割线========================
结合前几节的内容,写了个综合示例,包含8种阈值化方法
- 二进制阈值化
- 反二进制阈值化
- 截断阈值化
- 阈值化为0
- 反阈值化为0
- OTSU阈值化
- 自适应阈值化
- 双阈值化
其中阈值量可通过滑动条来调节,下面来看看程序是如何实现的。
=====================分割线========================
代码演示
/*综合示例,8种阈值化操作:1.二进制阈值化2.反二进制阈值化3.截断阈值化4.阈值化为05.反阈值化为06.OTSU阈值化7.自适应阈值化8.双阈值化*/#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> using namespace std;using namespace cv;//------------------------【宏定义部分】------------------------#define WINDOW_NAME "【几种阈值化操作】"//-----------------------【全局变量声明部分】------------------------Mat g_srcImage, g_grayImage, g_dstImage;//源图像、灰度图、结果输出图Mat g_dstTempImage1, g_dstTempImage2;//双阈值化部分图像const int g_maxVal = 255; //预设最大值 int g_nThresholdValue = 90;//初始阈值量int g_nTresholdType = 0;//阈值类型,并设初值为0int g_nLowThreshold = 60;//双阈值操作中的较小阈值量int g_nHighThreshold = 120;//双阈值操作中较大阈值量//-----------------------【全局函数声明部分】------------------------static void ShowHelpText();//显示界面帮助文字void on_Threshold(int, void*);//滑动条回调函数int OTSU(Mat grayImage); //OTSU法函数实现,返回一个阈值量Mat otsuThresh();//otsu阈值Mat adapThresh();//自适应阈值Mat doubleThresh();//双阈值//---------------【主函数】-------------------int main(){ShowHelpText();//------------【1】读取源图像并检查图像是否读取成功------------ g_srcImage = imread("D:\\OutPutResult\\ImageTest\\tower.jpg");if (!g_srcImage.data){cout << "读取图片错误,请重新输入正确路径!\n";system("pause");return -1;}imshow("【源图像】", g_srcImage);//--------------【2】灰度转换--------------cvtColor(g_srcImage, g_grayImage, COLOR_RGB2GRAY);//--------------【3】创建滑动条来控制阈值---------------namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);createTrackbar("阈值类型:", WINDOW_NAME, &g_nTresholdType, 7, on_Threshold);createTrackbar("阈值量:", WINDOW_NAME, &g_nThresholdValue, g_maxVal, on_Threshold);createTrackbar("小阈值量:", WINDOW_NAME, &g_nLowThreshold, g_maxVal, on_Threshold);createTrackbar("大阈值量:", WINDOW_NAME, &g_nHighThreshold, g_maxVal, on_Threshold);//--------------【4】结果在回调函数中显示---------------on_Threshold(0, 0);//-----------【5】轮询等待用户按键,如果ESC键按下则程序退出---------------while (1){char c = waitKey(10); if (c == 27) //按左上角ESC键退出。 27为ESC的ASCII码 break; }return 0;}//-------------------【滑动条的回调函数】---------------------void on_Threshold(int, void*){switch (g_nTresholdType){case 0:cout << "\n当前为【二进制阈值化】操作" << endl;threshold(g_grayImage, g_dstImage, g_nThresholdValue, 255, 0);imshow(WINDOW_NAME, g_dstImage); break;case 1:cout << "\n当前为【反二进制阈值化】操作" << endl;threshold(g_grayImage, g_dstImage, g_nThresholdValue, 255, 1);imshow(WINDOW_NAME, g_dstImage); break;case 2:cout << "\n当前为【截断阈值化】操作" << endl;threshold(g_grayImage, g_dstImage, g_nThresholdValue, 255, 2);imshow(WINDOW_NAME, g_dstImage); break;case 3:cout << "\n当前为【阈值化为0】操作" << endl;threshold(g_grayImage, g_dstImage, g_nThresholdValue, 255, 3);imshow(WINDOW_NAME, g_dstImage); break;case 4:cout << "\n当前为【反阈值化为0】操作" << endl;threshold(g_grayImage, g_dstImage, g_nThresholdValue, 255, 4);imshow(WINDOW_NAME, g_dstImage); break;case 5:cout << "\n当前为【OTSU阈值化】操作,阈值量不可调" << endl;g_dstImage = otsuThresh();imshow(WINDOW_NAME, g_dstImage); break;case 6:cout << "\n当前为【自适应阈值化】操作,阈值量不可调" << endl;g_dstImage = adapThresh();imshow(WINDOW_NAME, g_dstImage); break;case 7:cout << "\n当前为【双阈值化】操作,请分别调节大、小阈值量" << endl;g_dstImage = doubleThresh();imshow(WINDOW_NAME, g_dstImage); break;}}//---------------【OTSU法函数实现】---------------------- //功能:仅仅返回一个阈值量,还未实现阈值化//-------------------------------------------------------int OTSU(Mat grayImage){int nRows = grayImage.rows;//行数 int nCols = grayImage.cols;//列数 int threshold = 0; //初始化阈值 //------------【1】初始化统计参数------------ int nSumPix[256]; //用于灰度级中每个像素在整幅图像中的个数 float nProDis[256]; //用于记录每个灰度级占图像中的概率分布 for (int i = 0; i < 256; i++){nSumPix[i] = 0;nProDis[i] = 0;}//------------【2】统计灰度级中每个像素在整幅图像中的个数------------ for (int i = 0; i < nRows; i++){for (int j = 0; j < nCols; j++){nSumPix[(int)grayImage.at<uchar>(i, j)]++;}}//------------【3】计算每个灰度级占图像中的概率分布------------ for (int i = 0; i < 256; i++){nProDis[i] = (float)nSumPix[i] / (nCols*nRows);}//------------【4】遍历灰度级[0,255],计算出最大类间方差的阈值------------ float wb, wf; //比重. wb-背景部分; wf-前景部分 float u0_temp, u1_temp, u0, u1; //平均值 float delta_temp; //存放临时方差 double delta_max = 0.0; //初始化最大类间方差 for (int i = 0; i < 256; i++){wb = wf = u0_temp = u1_temp = u0 = u1 = delta_temp = 0;//初始化相关参数 for (int j = 0; j < 256; j++){//背景部分 if (j <= i){//当前i为分割阈值,第一类总的概率 wb += nProDis[j]; //比重 u0_temp += j*nProDis[j];}//前景部分 else{//当前i为分割阈值,第一类总的概率 wf += nProDis[i]; //比重 u1_temp += j*nProDis[j];}}//------------分别计算各类的平均值------------ u0 = u0_temp / wb;u1 = u1_temp / wf;//-----------计算最大类间方差------------ delta_temp = (float)(wb*wf*pow((u0 - u1), 2));//形如pow(x,y);其作用是计算x的y次方。 //------------依次找到最大类间方差下的阈值------------ if (delta_temp > delta_max){delta_max = delta_temp;threshold = i;}}//计算结束 return threshold; //返回OTUS计算出的阈值 }//---------------【OTSU阈值化函数实现】---------------------- Mat otsuThresh(){int otsuThreshold = OTSU(g_grayImage);//调用OTSU()阈值化所得到阈值cout << "--------且调用OTSU()阈值化所得阈值量为:" << otsuThreshold << endl;g_dstImage = Mat::zeros(g_grayImage.rows, g_grayImage.cols, CV_8UC1);//创建输出结果图像 //------------【利用得到的阈值实现二值化操作】------------ for (int i = 0; i < g_grayImage.rows; i++){for (int j = 0; j < g_grayImage.cols; j++){//阈值判断。 若该点值大于阈值,则设为255,否则设为0。 if (g_grayImage.at<uchar>(i, j) > otsuThreshold)g_dstImage.at<uchar>(i, j) = 255;elseg_dstImage.at<uchar>(i, j) = 0;}}return g_dstImage;}//---------------【自适应阈值化函数实现】---------------------- Mat adapThresh(){//------------【初始化相关变量】--------------- int blockSize = 3; //邻域块大小。取值3、5、7....等 int constValue = 10;int adaptiveMethod = 0;//自适应阈值算法int thresholdType = 1;//阈值类型/*自适应阈值算法0:ADAPTIVE_THRESH_MEAN_C1:ADAPTIVE_THRESH_GAUSSIAN_C--------------------------------------阈值类型0:THRESH_BINARY1:THRESH_BINARY_INV*///---------------【图像自适应阈值操作】------------------------- adaptiveThreshold(g_grayImage, g_dstImage, g_maxVal, adaptiveMethod, thresholdType, blockSize, constValue);return g_dstImage;}//---------------【双边阈值化函数实现】---------------------- Mat doubleThresh(){//小阈值对源灰度图像进行二进制阈值化操作 threshold(g_grayImage, g_dstTempImage1, g_nLowThreshold, g_maxVal, THRESH_BINARY);//大阈值对源灰度图像进行反二进制阈值化操作 threshold(g_grayImage, g_dstTempImage2, g_nHighThreshold, g_maxVal, THRESH_BINARY_INV);//矩阵"与运算"得到二值化结果 bitwise_and(g_dstTempImage1, g_dstTempImage2, g_dstImage); //对像素加和 return g_dstImage;}//---------------【显示界面帮助文字】---------------------- void ShowHelpText() {cout << "\t按键操作说明:" << endl << endl;cout << "\t\t键盘按键【Esc】-退出程序" << endl;cout << "\t\t阈值类型0- 二进制阈值化" << endl;cout << "\t\t阈值类型1- 反二进制阈值化" << endl;cout << "\t\t阈值类型2- 截断阈值化" << endl;cout << "\t\t阈值类型3- 阈值化为0" << endl;cout << "\t\t阈值类型4- 反阈值化为0" << endl;cout << "\t\t阈值类型5- OTSU阈值化" << endl;cout << "\t\t阈值类型6- 自适应阈值化" << endl;cout << "\t\t阈值类型7- 双阈值化" << endl;cout << "-------------------------------------------------" << endl << endl;}
========================分割线======================
显示结果
======================分割线======================
程序说明
其中阈值类型0--4,通过右上侧的阈值量来调节。
阈值类型5和6,为计算所得阈值量,不能调节。
阈值类型7,通过下面的,大、小阈值量来调节。
阈值类型7,通过下面的,大、小阈值量来调节。
=====================END=====================
阅读全文
0 0
- 【拜小白opencv】25-综合示例——8种阈值化操作【OTSU阈值化、自适应阈值化、二进制阈值化、反二进制阈值化、截断阈值化、阈值化为0、反阈值化为0,双阈值化】
- OpenCV-自适应阈值化
- 阈值化
- 阈值化
- 阈值化
- 阈值化
- 阈值化
- 图像otsu阈值化
- Otsu阈值化
- OTSU阈值化
- opencv双阈值化
- OpenCV 阈值化操作cvThreshold 和 自适应阈值cvAdaptiveThreshold操作
- opencv 中的Otsu阈值化
- 自适应阈值化 AdaptiveThreshold
- 自适应阈值化方法
- 自适应的阈值化
- OpenCV阈值化
- opencv-阈值化处理
- 【C语言】【unix c】进程的基础
- 淘宝头条,京东播报效果实现
- 文本搜索系统的评估
- 使用Cglib的BeanCopier实现Bean的复制
- 【C语言】【unix c】进程的创建
- 【拜小白opencv】25-综合示例——8种阈值化操作【OTSU阈值化、自适应阈值化、二进制阈值化、反二进制阈值化、截断阈值化、阈值化为0、反阈值化为0,双阈值化】
- 数据结构封装之《LinkList单向链表》
- 0网络安全小问答
- Dubbo学习笔记(一)
- 剑指offer(26)—二叉搜索树与双向链表
- 基于CAS的单点登录SSO[1]: 搭建CAS单点登录demo
- 基于雷达的安防视频监控系统软件设计
- Boost在Linux和windows下的编译 32位 64位
- 区块链目前的几大共识算法