作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

实现原理

物体识别是图像处理学在现实生活中较多的应用之一,目前最为流行的就是运用AI、机器学习等技术结合图像处理学,大量训练数据集,以实现智能且精确的识别。说到人工智能,很多人可能觉得它非常深奥和复杂,其实说白了它最底层的识别逻辑还是基于普通的图像分析,像特征提取、轮廓分析、比对分析等等,再在庞大的数据集中按照相似程度,分析出一个最可能的结果。

本文提供了一种相对简单的思路来实现绿叶识别,适合初学图像处理的新人研究参考。该方法为差分法:首先对图像进行高斯滤波处理预处理,平滑图像数据;其次,将图像颜色通道按RGB拆分,因为识别物为绿叶,其最明显的特征就是颜色;差分法,将绿色通道减去蓝色通道,之所以选择这两个通道,是因为蓝色通道和绿叶的关系较远,而红色搭配绿色可是黄色哦,绿叶中存在黄色特征信息可是再正常不过了;之后,对差分图进行OTSU阈值处理,得到掩膜感兴趣ROI区域;再后,就是对区域进行闭运算和孔洞闭合处理,保持区域完整性;最后,根据掩膜提取绿叶,完成。

功能函数代码

1)识别绿叶函数。

// 识别绿叶
Mat IdentifyLeaves(cv::Mat input)
{CV_Assert(input.channels() == 3);Mat temp, result, mask, hole;int row = input.rows;int col = input.cols;// 高斯滤波GaussianBlur(input, temp, Size(5, 5), 0);// 通道拆分vector<cv::Mat> c;split(temp, c);// 绿通道-蓝通道,提取绿色区域Mat diff = c[1] - c[0];threshold(diff, mask, 0, 255, THRESH_OTSU);// 闭运算封口cv::Mat element = getStructuringElement(MORPH_ELLIPSE, Size(9, 9));cv::morphologyEx(mask, mask, MORPH_CLOSE, element);// 孔洞闭合hole = 255 - mask;Clear_MicroConnected_Areas(hole, hole, row*col / 300);mask = 255 - hole;Clear_MicroConnected_Areas(mask, mask, row*col / 300);// 识别区域标记result = input.clone();result.setTo(Scalar(0, 0, 0), mask == 0);return result;
}

2)清除微小面积连通区函数,用于孔洞闭合。具体介绍见:

OpenCV-清除小面积连通域_翟天保的博客-CSDN博客

/**
* @brief  Clear_MicroConnected_Areas         清除微小面积连通区函数
* @param  src                                输入图像矩阵
* @param  dst                                输出结果
* @return min_area                           设定的最小面积清除阈值
*/
void Clear_MicroConnected_Areas(cv::Mat src, cv::Mat &dst, double min_area)
{// 备份复制dst = src.clone();std::vector<std::vector<cv::Point> > contours;  // 创建轮廓容器std::vector<cv::Vec4i>    hierarchy;// 寻找轮廓的函数// 第四个参数CV_RETR_EXTERNAL,表示寻找最外围轮廓// 第五个参数CV_CHAIN_APPROX_NONE,表示保存物体边界上所有连续的轮廓点到contours向量内cv::findContours(src, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_NONE, cv::Point());if (!contours.empty() && !hierarchy.empty()){std::vector<std::vector<cv::Point> >::const_iterator itc = contours.begin();// 遍历所有轮廓while (itc != contours.end()){// 定位当前轮廓所在位置cv::Rect rect = cv::boundingRect(cv::Mat(*itc));// contourArea函数计算连通区面积double area = contourArea(*itc);// 若面积小于设置的阈值if (area < min_area){// 遍历轮廓所在位置所有像素点for (int i = rect.y; i < rect.y + rect.height; i++){uchar *output_data = dst.ptr<uchar>(i);for (int j = rect.x; j < rect.x + rect.width; j++){// 将连通区的值置0if (output_data[j] == 255){output_data[j] = 0;}}}}itc++;}}
}

C++测试代码

#include <iostream>
#include <opencv2/opencv.hpp>using namespace std;
using namespace cv;void Clear_MicroConnected_Areas(cv::Mat src, cv::Mat &dst, double min_area);
Mat IdentifyLeaves(cv::Mat input);int main()
{Mat src = imread("test1.png");Mat result = IdentifyLeaves(src);imshow("src", src);imshow("result", result);waitKey(0);return 0;
}/**
* @brief  Clear_MicroConnected_Areas         清除微小面积连通区函数
* @param  src                                输入图像矩阵
* @param  dst                                输出结果
* @return min_area                           设定的最小面积清除阈值
*/
void Clear_MicroConnected_Areas(cv::Mat src, cv::Mat &dst, double min_area)
{// 备份复制dst = src.clone();std::vector<std::vector<cv::Point> > contours;  // 创建轮廓容器std::vector<cv::Vec4i>    hierarchy;// 寻找轮廓的函数// 第四个参数CV_RETR_EXTERNAL,表示寻找最外围轮廓// 第五个参数CV_CHAIN_APPROX_NONE,表示保存物体边界上所有连续的轮廓点到contours向量内cv::findContours(src, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_NONE, cv::Point());if (!contours.empty() && !hierarchy.empty()){std::vector<std::vector<cv::Point> >::const_iterator itc = contours.begin();// 遍历所有轮廓while (itc != contours.end()){// 定位当前轮廓所在位置cv::Rect rect = cv::boundingRect(cv::Mat(*itc));// contourArea函数计算连通区面积double area = contourArea(*itc);// 若面积小于设置的阈值if (area < min_area){// 遍历轮廓所在位置所有像素点for (int i = rect.y; i < rect.y + rect.height; i++){uchar *output_data = dst.ptr<uchar>(i);for (int j = rect.x; j < rect.x + rect.width; j++){// 将连通区的值置0if (output_data[j] == 255){output_data[j] = 0;}}}}itc++;}}
}// 识别绿叶
Mat IdentifyLeaves(cv::Mat input)
{CV_Assert(input.channels() == 3);Mat temp, result, mask, hole;int row = input.rows;int col = input.cols;// 高斯滤波GaussianBlur(input, temp, Size(5, 5), 0);// 通道拆分vector<cv::Mat> c;split(temp, c);// 绿通道-蓝通道,提取绿色区域Mat diff = c[1] - c[0];threshold(diff, mask, 0, 255, THRESH_OTSU);// 闭运算封口cv::Mat element = getStructuringElement(MORPH_ELLIPSE, Size(9, 9));cv::morphologyEx(mask, mask, MORPH_CLOSE, element);// 孔洞闭合hole = 255 - mask;Clear_MicroConnected_Areas(hole, hole, row*col / 300);mask = 255 - hole;Clear_MicroConnected_Areas(mask, mask, row*col / 300);// 识别区域标记result = input.clone();result.setTo(Scalar(0, 0, 0), mask == 0);return result;
}

测试效果

图1 原图1

图2 效果图1

图3 原图2

图4 效果图2

图5 原图3

图6 效果图3

本文只是提供了一种简单的识别思路,不可能满足所有的场景。举几个例子,如图6所示,因为孔洞闭合的缘故,导致绿叶间的间隙也被涵盖了;又或者,当所识别的绿叶没那么绿,有点偏暗时,蓝色通道的比例自然也提高了,此时用差分法效果就不会那么好了。

总而言之,不同的场景和需求还是需要结合实际进行算法的设计,天下没有一种算法是可以解决一切问题的,即便是人工智能也不可能,特殊问题特殊对待,加油!

如果函数有什么可以改进完善的地方,非常欢迎大家指出,一同进步何乐而不为呢~

如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!


期待一部即将上映的新电影《穿过寒冬拥抱你》~

OpenCV-差分法实现绿叶识别(图像差分+颜色通道)相关推荐

  1. 《OpenCv视觉之眼》Python图像处理十六:Opencv图像处理实战一之图像中的硬币检测

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  2. 2.图像作为函数 | 裁剪、颜色通道、图像相加_5

    目录 图像裁剪 颜色通道 图像相加 接着上一篇文章,我们继续学习图像处理方法. 图像裁剪 让我们使用选择行和列范围的方法从图像中提取更大的部分.这也称为裁剪图像. 让我们这次使用不同的图片.让我们看看 ...

  3. 高级UI之Paint(滤镜,颜色通道,矩阵运算)

    前言 在之前的几次课当中我们已经详细了解到整个android程序,从启动再到绘制的整体流程,从这中间我们又牵扯出了Canvas绘制图形的画板和我们的Paint控制色彩样式的画笔,那么之前基础篇我们就不 ...

  4. 使用Python,OpenCV,K-Means聚类查找图像中最主要的颜色

    Python,OpenCV,K-Means聚类查找图像中最主要的颜色 1. K-Means是什么? 2. 步骤 3. 效果图 4. 源代码 参考 对于肉眼来说,从一幅图中识别出主要颜色很容易.那怎么用 ...

  5. python如何实现图像中特定颜色的种类识别及特定颜色的占比代码

    使用Python实现图像中特定颜色的种类识别及特定颜色的占比代码,首先可以使用OpenCV库对图像进行处理,然后使用特定的函数来识别图像中特定颜色的种类,最后使用统计学方法来计算特定颜色在图像中的占比 ...

  6. opencv实战3-处理图像的颜色

    1 处理图像的颜色 1.1 提取指定的颜色区域 cv::floodFill() 函数 1.2 分割图像 cv::grabCut()函数,用于从静态图像中提取前景物体. 1.3 转换颜色的表示方法 HS ...

  7. OpenCV计算机视觉编程篇三《处理图像的颜色》

    前言 前期回顾: OpenCV计算机视觉编程篇二<操作像素> 上面这篇里面写了操作像素相关. 本章包括以下内容: 用策略设计模式比较颜色: 用 GrabCut 算法分割图像: 转换颜色表示 ...

  8. 【opencv】(1) 基础操作:图像视频读取、图像截取、颜色通道

    主要内容有:图像及视频的读取和保存.图像显示.转换灰度图.图像截取.颜色通道提取和组合 那我们开始吧. 1. 图像操作 首先我们导入opencv库,彩色图像一般都是由RGB(红绿蓝)三颜色通道构成,灰 ...

  9. 转载:【OpenCV入门教程之五】 分离颜色通道多通道图像混合

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/21176257 作者:毛星云(浅墨) ...

最新文章

  1. STL---string
  2. js运动动画的八个知识点
  3. 条件队列大法好:wait和notify的基本语义
  4. 统计学习方法第四章课后习题(转载+重新排版+自己解读)
  5. 动态Java代码注入
  6. git管理复杂项目代码
  7. mysql 重装之后_mysql重装之后 复制data
  8. Nginx通过地理位置限制访问
  9. SecureCRT for Mac(强大的终端SSH工具)
  10. 在Code-Behind中操作WebUserControl
  11. 帮助开发者快速创建响应式布局的Boilerplate - Responsive Boilerp...
  12. linux shell 学习时遇到的一些问题([: 11: y: unexpected operator)
  13. Android 来电自动接听
  14. Linux 下文件和目录的特点
  15. macbook插入耳机不出声
  16. python123 第四次作业_第四次作业
  17. python 2 入门
  18. 孙向晖-《领域驱动设计》读书心得交流会-UMLChina讲座-实录
  19. 电脑录音软件哪个好用?如何录制声音?
  20. 阻塞/非阻塞 同步/异步

热门文章

  1. Hey,微信广告收到了吗?你哪个阶层的?
  2. Linux运维之道之网络基础学习1.3
  3. android sdk manager 更新失败
  4. 斯坦福NLP笔记51 —— An Intro to Parts of Speech and POS
  5. SSH家政服务系统设计与实现答辩PPT免费下载
  6. 【论文写作】毕业论文写作套路之正文(1)
  7. python逐行读取txt文件-在python 3.4上逐行读取文本文件
  8. 浏览器字体大小设置_max浏览器app-max浏览器安卓版
  9. win7计算机记忆窗口,Win7系统关闭和打开搜索记忆功能的方法(图文教程)
  10. PSOLA基音同步叠加算法