在前面我们已经完成通过OpenCV读取图片在Picture Control中并自适应显示。下面我们很自然的需要对读取的图片进行处理,处理完之后很自然的想到要看看效果。所以今天的笔记是通过OpenCV灰度处理图像并显示结果。

需求描述

如图所示,

S1,上面的按钮打开资源管理器,载入一个图片到左边的Picture Control自适应显示;

S2,下面一个按钮把载入的图片通过OpenCV灰度处理后,在右边的Picture Control自适应显示;

S3,通过下面的滚动条来调整阈值,观察并感性认知,不同阈值下灰度化的不同效果。

灰度处理

以我这新手村的理解,如果说数字图像预处理的最后一步是图像的二值化,那么第一步就是图像的灰度化。

图像灰度化处理的目的简单点说就是把图像数字化,方便技术开发和分析。

灰度图像每个像素只需一个字节存放灰度值(又称强度值、亮度值),灰度范围为0-255,灰度图像通常在单个电磁波频谱(如可见光)内测量每个像素的亮度得到的。用于显示的灰度图像通常用每个采样像素8位的非线性尺度来保存,这样可以有256级灰度。这种精度刚刚能够避免可见的条带失真,并且非常易于编程。

二值化

图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出明显的黑白效果。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。

从编程的角度,可以理解为把图像中的复杂像素信息,转换成非0即1,非1就0的二值化数据,便于我们计算。

//第二个按钮的响应事件代码
void CmyMFCDlg::OnBnClickedBinary()
{// TODO: 在此添加控件通知处理程序代码Mat dst_mat;//左边载入的图片对象//S1,灰度处理cv::cvtColor(src_mat, dst_mat, cv::COLOR_BGR2GRAY);//S2,开始二值化//第二个和第三个参数是阀值,决定了二值化显示的效果.如果设定不正确可能图像显不出来  cv::threshold(dst_mat, dst_mat, 127, 255, cv::THRESH_BINARY);//S3,展示图片处理后的效果DrawMat(dst_mat, IDC_STATIC_RESULT);
}

关于二值化方法cv::threshold简单说下,一共5个参数,重点注意下第3和第5个参数。

第3个是阈值,第5个是阈值算法类型。

这里的阈值怎么理解?比如我们的相机固定的角度和参数去拍摄一个照片,那么受光源变化(比如阳光变化,比如灯光明暗)的影响,出来的图像也可能会不一样。我们不能简单粗暴的去对图片二值化,这样会导致可能丢失本该是1的像素信息,却收集放大化了本该是0的像素信息。

大多数时候,在工业流水线环境下,由于光源和角度相对固定,所以这阈值是可以通过反复调试后的经验值来设定一个最佳阈值和阈值算法类型。但是在光源环境变化较多的时候,这阈值需要我们更多的精力去计算。

我们这就来看看同一个图片,在不同阈值的图片效果:

看到滑块的变化,导致了阈值的变化,也导致了二值化后的效果在变化,哪些值是有用的,哪些值会计算出什么结果,这都会有阈值不同带来不同的结果。

知道这阈值的影响之强大了吧?

至于cv::threshold第5个参数阈值算法类型,也是和阈值相辅相成的,这些网上都比较全面,也比较容易查阅,就不多说了。

最后贴下文首提到的第3点需求,OpenCV处理过后的图像要在Picture Control展现出来。

//参数1:要显示的图对象
//参数2:Picture Control控件的ID
void CmyMFCDlg::DrawMat(cv::Mat& img, UINT nID)
{CRect rect;cv::Mat imgTmp;GetDlgItem(nID)->GetClientRect(&rect);  // 获取控件大小cv::resize(img, imgTmp, cv::Size(rect.Width(), rect.Height()));// 缩放Mat并备份// 再重新灰度处理下,备用 switch (imgTmp.channels()){case 1:cv::cvtColor(imgTmp, imgTmp, CV_GRAY2BGRA); // GRAY单通道break;case 3:cv::cvtColor(imgTmp, imgTmp, CV_BGR2BGRA);  // BGR三通道break;default:break;}int pixelBytes = imgTmp.channels() * (imgTmp.depth() + 1); // 计算一个像素多少个字节// 制作bitmapinfo(数据头)BITMAPINFO bitInfo;bitInfo.bmiHeader.biBitCount = 8 * pixelBytes;bitInfo.bmiHeader.biWidth = imgTmp.cols;bitInfo.bmiHeader.biHeight = -imgTmp.rows;bitInfo.bmiHeader.biPlanes = 1;bitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);bitInfo.bmiHeader.biCompression = BI_RGB;bitInfo.bmiHeader.biClrImportant = 0;bitInfo.bmiHeader.biClrUsed = 0;bitInfo.bmiHeader.biSizeImage = 0;bitInfo.bmiHeader.biXPelsPerMeter = 0;bitInfo.bmiHeader.biYPelsPerMeter = 0;// Mat.data + bitmap数据头 -> MFCCDC* pDC = GetDlgItem(nID)->GetDC();::StretchDIBits(pDC->GetSafeHdc(),0, 0, rect.Width(), rect.Height(),0, 0, rect.Width(), rect.Height(),imgTmp.data,&bitInfo,DIB_RGB_COLORS,SRCCOPY);ReleaseDC(pDC);
}

身为MFC和图像处理的双重新手,学习起来比较吃力,但日积月累,总会有收获,加油了!

OpenCV+MFC学习笔记(二):OpenCV二值化处理图像并在Picture Control中并自适应显示相关推荐

  1. OpenCV学习笔记(十二):边缘检测:Canny(),Sobel(),Laplace(),Scharr滤波器

    OpenCV学习笔记(十二):边缘检测:Canny(),Sobel(),Laplace(),Scharr滤波器 1)滤波:边缘检测的算法主要是基于图像强度的一阶和二阶导数,但导数通常对噪声很敏感,因此 ...

  2. opencv 二值化 python_opencv-python图像二值化函数cv2.threshold函数详解及参数cv2.THRESH_OTSU使用...

    cv2.threshold()函数的作用是将一幅灰度图二值化,基本用法如下: #ret:暂时就认为是设定的thresh阈值,mask:二值化的图像 ret,mask = cv2.threshold(i ...

  3. 【计算机视觉】opencv入门学习笔记Part.1

    [计算机视觉]opencv入门学习笔记Part.1 1 前言 1.1 opencv概述(摘取自百度百科) 1.2 图像概念引入 1.3 安装opencv库 2 图像基本操作 2.1 图像的读取 2.2 ...

  4. Kinect开发学习笔记之(二)Kinect开发学习资源整理

    Kinect开发学习笔记之(二)Kinect开发学习资源整理 zouxy09@qq.com http://blog.csdn.net/zouxy09 刚刚接触Kinect,在网上狂搜资料,获得了很多有 ...

  5. tensorflow学习笔记(三十二):conv2d_transpose (解卷积)

    tensorflow学习笔记(三十二):conv2d_transpose ("解卷积") deconv解卷积,实际是叫做conv_transpose, conv_transpose ...

  6. 汇编入门学习笔记 (十二)—— int指令、port

    疯狂的暑假学习之  汇编入门学习笔记 (十二)--  int指令.port 參考: <汇编语言> 王爽 第13.14章 一.int指令 1. int指令引发的中断 int n指令,相当于引 ...

  7. QT学习笔记(十二):透明窗体设置

    QT学习笔记(十二):透明窗体设置 创建 My_Widget 类 基类为QWidget , My_Widget.cpp 源文件中添加代码 #include "widget.h" # ...

  8. Unity3d之HashSlash学习笔记之(二)--角色基础类的构建

    Hash&Slash学习笔记之(二)--角色基础类的构建 BaseStat类的构建 基本成员变量: _baseValue //基础属性值 _buffValue //增加的buff值 _expT ...

  9. 模电学习笔记(十二)——跨阻放大器

    模电学习笔记(十二) 跨阻放大器 跨组运算放大器是将电流信号转换成为电压信号,电流到电压增益基于反馈电阻. 设计目标: 输入 输出 带宽 电源 0A 100uA 0V 7V 20kHz 15V -15 ...

最新文章

  1. flask源码学习-路由的注册与请求处理的过程
  2. VMware虚拟产品简介
  3. java 打破双亲委派_JVM - 打破双亲委派机制(模拟热加载)
  4. background-position 详解
  5. 编译原理实验语义分析_Windows MVSC编译器实现Xtended Flow Guard(XFG)保护机制的原理分析...
  6. 网络爬虫终篇:向10万级网易云用户发送定向消息
  7. wxpy 0.1.2微信机器人 / 优雅的微信个人号API
  8. excel帮助文档_可以惊艳到你的6个excel基础技巧
  9. leetcode 112 --- 二叉树根节点到叶子节点和为指定值的路径
  10. android 生命周期流程图,Android Studio ——Service的生命周期
  11. 聆听无声的话语:手把手教你用ModelArts实现手语识别
  12. 一句话菜刀 php eval,如何基于菜刀PHP一句话实现单个文件批量上传?
  13. windows7 安装docker
  14. 七款顶级HTML5编辑器带你飞
  15. 程序员小助手 | Emacs,最强编辑器,没有之一
  16. mysql ibd文件清理_MYSQL .ibd文件数据恢复
  17. 80后的青春里,总有散不去的周杰伦
  18. fedora35下配置grub2主题
  19. 直播公司转让,转让直播文网文-网络文化经营许可证
  20. 基于C90标准的C语言开发工具

热门文章

  1. 使用TCP RFC 1323进行Windows XP网络性能优化
  2. 16.Oracle杂记——数据字典dba_tab_ privs
  3. UNCTAD和阿里巴巴商学院启动面向亚洲企业家的互联网创业者计划
  4. 学习Unity相关网站博客和开源项目
  5. matlab什么专业要学,【读书1】【2017】MATLAB与深度学习——什么是机器学习(1)
  6. python房地产成本管理软件_房地产项目成本测算软件
  7. 利用用户搜索词生成商品标题信息——阿里巴巴IDST
  8. 游标卡尺数字乱跳修复方法
  9. 最新广东省知识产权贯标奖励及补助政策汇总大全,包括广州、深圳等
  10. ArcGIS不同图层的线要素合并