《零基础入门RM之图像预处理》(个人笔记)

写在前面的话:

本博客以上交大2019赛季步兵视觉代码为基础学习,仅作个人笔记使用,若有侵权请在评论区留言或私信我。

图像预处理

1-1 RGB通道加权处理

描述: 使用通道拆分函数对载入的视频或图像进行通道加权处理通道拆分:一张图片由RGB三原色混合而成,通道拆分就是把原图拆分成R、G、B三个通道,方便我们后续对图片进行识别和处理,在RM中一般只用识别(蓝色/红色)。

上交大源码:

1.	cv::Mat color_channel;               //颜色通道  
2.	std::vector<cv::Mat> channels;       // 定义一个空的vector容器储存图像 
3.	  
4.	cv::split(src, channels);               /************************/  
5.	if (enemy_color == ENEMY_BLUE) {         /*                      */  
6.	    color_channel = channels[0];        /* 根据目标颜色进行通道提取 */  
7.	} else if (enemy_color == ENEMY_RED) {    /*                      */  
8.	    color_channel = channels[2];        /************************/  
9.	} 

知识点:
1、 Mat //opencv中独有,相当于C/C++中的int类型专用于储存图像
参考文档:Mat类型详解
2、 vector //可以理解为容器或动态数组

问题:

用cv::Mat channels; 定义和std::vectorcv::Mat channels;
定义的效果一样为什么不用cv::Mat channels;定义?

解答:

(1)输出数组为定长容器,而vector为变长容器
(2)vector可用.at()以避免a[-1]访问越界的问题
(3)vector还提供了.size()和.empty(),而输出数组只能用sizeof()/strlen()
(4)以及遍历计数来获取大小和是否为空
(5)vector()和array会自动释放。

参考文档:

https://www.cnblogs.com/HL-space/p/10546605.html
https://blog.csdn.net/weixin_41743247/article/details/90635931
3、函数: split(通道拆分) //用于RGB通道加权处理,我们用它分离出红蓝两个通道
函数原型:

C++: void split(const Mat& src,       // 填我们需要进行分离的多通道数组   
                      Mat* mvbegin    //填输出数组或者输出的vector容器  
                );    
C++: void split(InputArray          m, // 填我们需要进行分离的多通道数组  
                 OutputArrayOfArrays mv //填输出数组或者输出的vector容器  
                );    

参考文档:https://blog.csdn.net/qq_35294564/article/details/81058226
1-2 阀值化(二值化)

描述: 图像二值化( ImageBinarization)就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。相当于将输入图像中阈值外的像素全部置0,使得阈值内目标凸出,便于PC进行灯条识别。

上交大源码:

1.	cv::Mat src_bin_light, src_bin_dim;  
2.	int light_threshold;  
3.	if(enemy_color == ENEMY_BLUE){  
4.	    light_threshold = 225;  
5.	}else{  
6.	    light_threshold = 200;  
7.  }  
8.	cv::threshold(color_channel, src_bin_light, light_threshold, 255, CV_THRESH_BINARY); // 二值化对应通道  
9.  if (src_bin_light.empty()) return false;  
10. imagePreProcess(src_bin_light);                             // 开闭运算  
11.	cv::threshold(color_channel, src_bin_dim, 140, 255, CV_THRESH_BINARY); // 二值化对应通道  
12.	 if (src_bin_dim.empty()) return false;  
13.	 imagePreProcess(src_bin_dim);                               // 开闭运算 

知识点:
1、函数:cv::threshold() //通道拆分后,再通过二值化将单通道内的目标凸现
函数原型:

double cv::threshold(InputArray     src,
                      //源图像,可以为8位的灰度图,也可以为32位的彩色图像。  
	                 OutputArray    dst,//输出图像  
	                 double         thresh,//阈值  
	                 double         maxval,//dst图像中最大值  
	                 int            type   //阈值类型  
	                 )  

参考文档:https://blog.csdn.net/qq_37385726/article/details/82015545

2、问题:

为什么二值化阈值为maxValue_gary * 0.7 或225/200/140?

解答(未完全):

在上交大中使用两个不同的二值化阈值同时进行灯条提取,减少环境光照对二值化这个操作的影响。同时剔除重复的灯条,剔除冗余计算,即对两次找出来的灯条取交集。

3、 问题:

src_bin_light.empty()有什么用?

解答:

用于判断 .empty()前面的容器是否为空,若为空则置0

参考文档:.empty()的用法
1-3 开闭运算(腐蚀与膨胀)

描述: 通常,由于噪声的影响,图象在阈值化(二值化)后所得到边界往往是很不平滑的,物体区域具有一些噪声孔,背景区域上散布着一些小的噪声物体。连续的开和闭运算可以有效地改善这种情况。有时需要经过多次腐蚀之后再加上相同次数的膨胀,才可以产生比较好的效果。

上交大源码:

1.	// 开闭运算,上交大采用的是先开运算->闭运算
2.	static void imagePreProcess(cv::Mat &src) {  
3.	static cv::Mat kernel_erode = getStructuringElement(cv::MORPH_RECT, cv::Size(3, 5));  
4.	erode(src, src, kernel_erode);  
5.	  
6.	static cv::Mat kernel_dilate = getStructuringElement(cv::MORPH_RECT, cv::Size(3, 5));  
7.	dilate(src, src, kernel_dilate);  
8.	  
9.	static cv::Mat kernel_dilate2 = getStructuringElement(cv::MORPH_RECT, cv::Size(3, 5));  
10.	dilate(src, src, kernel_dilate2);  
11.	  
12.	static cv::Mat kernel_erode2 = getStructuringElement(cv::MORPH_RECT, cv::Size(3, 5));  
13.	erode(src, src, kernel_erode2);  
14.	}  

知识点:
1、开运算与闭运算
(1)开运算: 腐蚀->膨胀
先腐蚀后膨胀的过程称为开运算。用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。
(2)闭运算: 膨胀->腐蚀
先膨胀后腐蚀的过程称为闭运算。用来填充物体内细小空洞、连接邻近物体、平滑其边界的同时并不明显改变其面积。
参考文档:https://blog.csdn.net/caojinpei123/article/details/81916005

2、腐蚀与膨胀
函数:erode(腐蚀) //相当于减肥,将锚点以外的部分去除
函数原型:

void erode(  
           InputArra src,  
           OUtputArray dst,  
           InputArra kernel,  
           Point anchor=Point(-1,-1),  
           int iterations=1,  
           int borderType=BORDER_CONSTANT,  
           const Scalar& borderValue=morphologyDEfaultBoderValue()  
           );  

函数:dilate(膨胀) //相当于增肥,将锚点以为的部分增加一圈像素点
函数原型:

void dilate(  
	           InputArra src,  
               OUtputArray dst,  
               InputArra kernel,  
	           Point anchor=Point(-1,-1),  
	           int iterations=1,  
	           int borderType=BORDER_CONSTANT,  
	           const Scalar& borderValue=morphologyDEfaultBoderValue()  
           );  

函数:getStructuringElement //该函数会返回指定形状和尺寸的结构元素

其实我对这个函数的用法也不是很清楚但是在《opencv3编程入门》中提到一般将这个函数与开闭运算配合使用,所以大家有需要的可以自行了解。

函数原型:

Mat getStructuringElement(int  shape,   //表示内核的形状,有三种形状可以选择  
                          Size esize,                 //内核的尺寸  
                          Point anchor = Point(-1, -1)//锚点的位置  
                          );  
//这里需要注意的是内核的尺寸好像一般用不到,可以直接省略。

《opencv3编程入门》截图pdf P208
在这里插入图片描述
《opencv3编程入门》截图pdf P208

1-4 轮廓检测
描述: 轮廓提取使用的是OpenCV自带的函数findContours具体原理可以百度(其实我业不太清楚)
上交源码:

1.	std::vector<std::vector<cv::Point>> light_contours_light, light_contours_dim;  
2.	std::vector<cv::Vec4i> hierarchy_light, hierarchy_dim;  
3.	cv::findContours(src_bin_light, light_contours_light, hierarchy_light, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);  
4.	cv::findContours(src_bin_dim, light_contours_dim, hierarchy_dim, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);  

知识点:
1、vector<vector>与vector
参考文档:https://blog.csdn.net/Ahuuua/article/details/80593388
2、函数:findContours() //原理的话可以翻墙或者百度
函数原型:

void cv::findContours   (  
                            InputOutputArray        image,  
                            OutputArrayOfArrays     contours,  
                            OutputArray     hierarchy,  
                            int     mode,  
                            int     method,  
                            Point   offset = Point()   
                        )   

参考文档:opencv学习(四十)之寻找图像轮廓findContours()

感谢你的认真阅读,如果觉得对你有帮助的话可以给我点个赞,谢谢!

交龙2019赛季步兵视觉代码详解

  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值