OpenCV中通过滑动条阈值分割多通道图像
来源:互联网 发布:软件实施过程文档 编辑:程序博客网 时间:2024/06/05 16:57
1、阈值分割
阈值分割法是一种基于区域的图像分割技术。其基本原理是:通过设定不同的特征阈值,把图像象素点分为若干类。根据图像阈值化算法所依据的信息源,可将阈值化方法分为五类:1) 基于聚类的方法:数据聚类中,总的数据集被划分为属性相似的子类,例如将灰度级聚类成为两部分:前景物体部分和背景部分。2) 基于直方图的方法:在直方图的峰、谷和直方图的圆滑曲线上进行分析。3) 基于熵的方法:熵方法将区域分为背景区域和前景区域,前景区域通常是物体部分(在一些热红外图像中,背景部分是物体) 。该方法是通过最小化一个熵函数来实现的,交叉熵函数包含了介于原图和其二值图像之间的保留信息。4) 基于空间方法:使用概率密度函数模型,考虑全局范围内的像素之间的相似关系。5) 基于自适应方法:局部方法不能决定单一的阈值,自适应阈值依赖于局部图像特点。
这里,我们仅结合OpenCV中的API函数 threshold 来介绍一下阈值化。threshold函数原型如下:
double threshold(InputArray src, OutputArray dst, double thresh, double maxVal, int thresholdType)
Parameters:
第一个参数: 输入的灰度图像的地址。
第二个参数: 输出图像的地址。
第三个参数: 进行阈值操作时阈值的大小。
第四个参数: 设定的最大灰度值(该参数运用在二进制与反二进制阈值操作中)。
第五个参数: 阈值的类型。
最后一个参数是阈值化类型,函数一共提供了五种类型(图片来自opencv官网)。
1)二进制阈值化,参数值为0.
很好理解,像素值大于阈值设为255,反正设为0;
2)反二进制阈值化
与二进制阈值化类似,只不过大于阈值设为0,反之设为255;
3)截断阈值化
图像中大于该阈值的像素点被设定为该阈值,小于该阈值的保持不变;
4)阈值化为0
大于阈值的像素点不进行任何改变,其余灰度值全部变为0;
5)反阈值化为0
与阈值化类似,大于阈值的像素设为0,其余不做任何改变。
此外,OpenCV中应用极为广泛的阈值化API函数为adaptiveThreshold(自适应阈值化函数),详细用法参考OpenCV文档。
2、Trackbar
OpenCV提供了API函数createTrackbar,这使我们在设置参数的时候可以很方便的同程序交互。creatTrackbar函数原型如下:
int createTrackbar(const string& trackbarname, const string& winname, int* value, int count, TrackbarCallback onChange=0, )
第一个参数,const string&类型的trackbarname,表示轨迹条的名字,用来代表我们创建的轨迹条。
第二个参数,const string&类型的winname,填窗口的名字,表示这个轨迹条会依附到哪个窗口上,即对应namedWindow(),创建窗口时填的某一个窗口名。
第三个参数,int* 类型的value,一个指向整型的指针,表示滑块的位置。并且在创建时,滑块的初始位置就是是由该变量当前的值。
第四个参数,int类型的count,表示滑块可以达到的最大位置的值。PS:滑块最小的位置的值始终为0。
第五个参数,TrackbarCallback类型的onChange,首先注意他有默认值0。这是一个指向回调函数的指针,每次滑块位置改变时,这个函数都会进行回调。并且这个函数的原型必须为void Foo(int,void*);其中第一个参数是轨迹条的位置,第二个参数是用户数据(看下面的第六个参数)。如果回调是NULL指针,表示没有回调函数的调用,仅第三个参数value有变化。
第六个参数,void*类型的userdata,他也有默认值0。这个参数是用户传给回调函数的数据,用来处理轨迹条事件。如果使用的第三个参数value实参是全局变量的话,完全可以不去管这个userdata参数。
Demo程序如下:
#include <iostream>#include <cstring>#include "opencv2/core/core.hpp"#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"using namespace std;using namespace cv;// 全局变量定义及赋值int threshold_type = 3;int const max_type = 4; //阈值化类型int threshold_Bvalue = 0; //B通道阈值设定int threshold_Gvalue = 0; //G通道阈值设定 int threshold_Rvalue = 0; //R通道阈值设定int const max_value = 255; int const max_BINARY_value = 255;Mat src, dst;//创建一个图像向量vector<Mat> planes; char* window_name = "Threshold Func";char* trackbar_type = "TrackbarType"; //0: Binary 1: Binary Inverted 2: Truncate //3: To Zero 4: To Zero Invertedchar* trackbar_Bvalue = "B_Value";char* trackbar_Gvalue = "G_Value";char* trackbar_Rvalue = "R_Value";/// 自定义函数声明void Threshold_Func( int, void* );int main(){ //加载一幅图片 src = imread( "test.jpg", 1 ); // 将图片转换成灰度图片 //cvtColor( src, src_gray, CV_RGB2GRAY ); //将多通道图像分割为若干单通道图像 split(src, planes); // 创建一个窗口显示图片 namedWindow( window_name, CV_WINDOW_AUTOSIZE ); // 创建滑动条来控制阈值 createTrackbar( trackbar_type, window_name, &threshold_type, max_type, Threshold_Func ); createTrackbar( trackbar_Bvalue, window_name, &threshold_Bvalue, max_value, Threshold_Func ); createTrackbar( trackbar_Gvalue, window_name, &threshold_Gvalue, max_value, Threshold_Func ); createTrackbar( trackbar_Rvalue, window_name, &threshold_Rvalue, max_value, Threshold_Func ); // 初始化自定义的阈值函数 Threshold_Func( 0, 0 ); // 等待用户按键。如果是ESC健则退出等待过程。 while(true) { int c; c = waitKey( 20 ); if( (char)c == 27 ) { break; } }}//自定义的阈值函数void Threshold_Func( int, void* ){ /* 0: 二进制阈值 1: 反二进制阈值 2: 截断阈值 3: 0阈值 4: 反0阈值 */ dst.create(src.size(),src.type()); vector<Mat> thredplanes; split(dst,thredplanes); threshold( planes[0], thredplanes[0], threshold_Bvalue, max_BINARY_value,threshold_type ); threshold( planes[1], thredplanes[1], threshold_Gvalue, max_BINARY_value,threshold_type ); threshold( planes[2], thredplanes[2], threshold_Rvalue, max_BINARY_value,threshold_type ); //将三个单通道图像重新合并为一个三通道图像 merge(thredplanes,dst); //显示dst图像 imshow( window_name, dst );}
运行结果:
程序说明:
1)先读取一副图片,如果是图片颜色类型是BGR三通道类型,则分离为三个单通道图像。
vector<Mat> planes; //创建图像向量,用来存放src分割后的单通道图像split(src, planes); //分割原始图像为若干单通道图像,split函数原型为 //void split(const Mat& mtx, vector<Mat>& mv) //对偶运算为void merge(const vector<Mat>& mv, OutputArray dst)
2)创建一个窗口来显示该图片可以检验转换结果
3)创建滑动条。
第一个滑动条作用:选择阈值类型:二进制,反二进制,截断,0,反0。
二、三、四滑动条作用:分别选择BGR通道(分割后)阈值的大小。
4)等待用户拖动滚动条来输入阈值类型以及阈值的大小,或者是用户键入ESC健退出程序。
3、Nao红球识别
我们在Nao机器人的远程环境下进行红球识别,光照等外部环境对识别的结果有很大影响,所以一般将BGR颜色空间转换到HSV空间。无论如何选择颜色空间,进行多通道的阈值分割是保证后续识别的重要步骤。此外,用Nao机器人摄像头获取图像时,白平衡及曝光等参数的设定也至关重要,如果用滑动条的方式去寻找合适的参数,也不失为一种高效的方法!
- OpenCV中通过滑动条阈值分割多通道图像
- opencv 图像阈值分割图像
- opencv阈值法分割图像
- opencv我的单通道阈值分割
- opencv split图像通道分割
- Opencv多通道图像混合-滚动条
- 利用OpenCV实现图像的阈值分割
- Opencv 图像分割: 阈值化分割 区域分割 边缘分割
- 批量图像自动分割 grabcut+阈值分割 opencv
- opencv阈值法分割图像
- 【Opencv】大律法求阈值+分割图像计算像素比
- 基于阈值图像分割
- OpenCV--阈值分割-threshold()
- opencv中几种阈值分割
- 图像的阈值以及滑动条的建立
- Opencv图像识别从零到精通(15)-----阈值分割、固定阈值Threshold、自适应阈值分割adaptiveThreshold、OSTU大津法
- 基于opencv源程序的滑动条实现阈值变换
- opencv多通道图像转单通道
- ajax 局部刷新,返回json字符串
- 页面某个div固定在顶部
- 余弦相似性:找出相似文章
- solr入门教程
- AnimationDrawable连续new,star动画效果没有?
- OpenCV中通过滑动条阈值分割多通道图像
- linux 子目录赋权限
- VS项目属性的一些配置项的总结(important)
- localStorage使用
- UVALive 2963-Hypertransmission-贪心
- maven仓库调用顺序
- 自己动手写ORM框架-java
- php 设置 session详解(过期,失效,有效期)
- android手把手教你开发launcher(五)