基于Opencv的简单图像处理
实验环境
本实验均在笔记本电脑完成,电脑的配置如表1所示:
系统 |
Windows 10 家庭版 |
处理器 |
英特尔 Core i5-6200 @ 2.30GHz 双核 |
主板 |
宏碁 Zoro_SL |
内存 |
16G(金士顿 DDR3 1600MHz) |
主硬盘 |
西数 WDC WD10JPVX-22JC3T0 |
显卡 |
NVIDIA GeForce 940M(4G) |
显示器 |
奇美 CMN15C4(15.5英寸) |
表1:电脑配置
本实验使用Opencv对图像处理,使用MFC对图像显示,具体介绍如表2所示:
Visual Studio 2019 |
MFC |
Opencv3.3.0 |
表2:环境介绍
主要原理
由于OpenCV常用的界面只是单纯的打开图像窗口,相关界面控件和工具较少且不美观,故使用MFC制作界面,而用OpenCV单纯做图像处理。此时便需要在MFC中显示OpenCV所用的图片,现有以下三种方法可以实现:参考(链接)
(1)、嵌套。直接将OpenCV窗口嵌套到MFC的Pictrue Control控件中。此方法既能直接显示图片,也可直接使用OpenCV的鼠标按键事件,但对于鼠标滚轮事件只能使用MFC本地的滚轮函数。
(2)、转换。将OpenCV读取或处理的图片转换格式,使之成为MFC的Pictrue Control控件可显示的图片格式。
(3)、保存。将OpenCV读取或处理的图片保存为本地图片,然后用MFC读取图片的方法读取并显示。此方法是笨方法,在特定情况下使用,保存和读取图片比较耗时,但无需转换格式,同样只能使用MFC的鼠标事件。
本实验中使用的是“转换”方式将Opencv处理后的图像显示到MFC的控件上,具体代码如下:
//显示到第一个Pic控件 void CMFC_DEMODlg::ShowPic_1(Mat input_1) { Mat imagedst; // Mat是在矩阵中存储图片的数据结构 CRect rect; //定义矩阵类,记录一个矩形信息(四个坐标点等) /* GetDlgItem(IDC_STATIC):获取控件IDC_STATIC句柄 GetClientRect(&rect):获取句柄指向控件区域的大小 */ GetDlgItem(IDC_STATIC)->GetClientRect(&rect); //获取图像大小(长、宽、高等) Rect dst(rect.left, rect.top, rect.right, rect.bottom); //调整图像大小,含有格式转换 resize(input_1, imagedst, cv::Size(rect.Width(), rect.Height())); imshow("view", imagedst); }
配置MFC
在VS中添加MFC的组件即可,如图1所示:
图1:MFC配置
Opencv介绍
人类获取的所有信息中,视觉信息占绝大多数。在大数据时代,图像、视频等视觉信息载体也是最主要的数据来源之一,在铁路工程、公路、机场、医学、生物学、军事等领域有着广泛的应用。由于计算机视觉涉及多个领域的专业知识,以及视觉任务的多样性和视觉对象的复杂性,这使得计算机是视觉研究具有一定的困难性。
Opencv是跨平台、跨语言、开源、支持模块多、功能强大、性能高、稳定的机器学习库和计算机视觉库,其全称为Open Source Computer Vision Library。OpenCV是由Intel公司组织开发的,自1999年问世以来,逐渐成为计算机视觉研究领域人员的标准库工具。
Opencv中包含了大量的模块,highgui、imgproc和core是最基础的三个模块,介绍了图像处理基础方法的原理,也是研究Opencv的开始。Highgui模块包含用于在Opencv中输入、存储、输出图像的UI接口;core模块包含了Opencv一些基本运算函数和最核心的数据结构;imgproc模块包含了Opencv中图像处理的基本方法,包括图像的平滑、对比度增强、形态学处理、阈值分割、边缘检测几何图像的检测和拟合、傅里叶变换、频率域滤波等。Opencv中也包含了更高层次层次饿的图像处理方法的相关模块,包括用于机器学习的ml模块,如神经网络、随机森林、支持向量机等;实现对目标检测功能的objdetect模块,如基于HOG的汽车、行人的检测,基于LBP、Haar特征的人脸等目标的检测;针对视频处理的video模块,如运行物体的跟踪、背景建模、前景检测等。由此可见,在计算机视觉研究领域的所有方向,Opencv几乎都可以实现。Opencv提供的标准统一的函数和数据结构的混合能够更好地检测、分割是识别出物体的特征,这些优势都为图像处理研究奠定了良好的基础。
Opencv在VS中配置
首先,先下载Opencv,进行安装;然后配置电脑系统变量;最后设置项目属性,主要分为Debug和Release两种调试方法,分别设置项目的通用属性:VC++目录—包含目录和库目录和链接器:输入-添加依赖项,具体如图2、图3所示:
图2:VC++配置
图3:链接器配置
功能介绍
效果分为主页面,即一个窗口,可以显示图像和处理后的图像,最上面有三个菜单里面有实现主要的功能,具体的如图4、图5、图6、图7所示:
图4:主界面
图5:文件操作
图6:图像处理
图7:实时图像处理
灰度化和二值化
(1)灰度化
图像灰度化核心思想是 R = G = B ,这个值也叫灰度值
主要代码如下,运行结果如图8所示:
//转换成灰度图像 Mat CMFC_DEMODlg::ImageGray1() { Mat huidu, out2; cvtColor(image, huidu, COLOR_BGR2GRAY); return huidu; }
图8:灰度化
(2)二值化
从灰度图像中获取二进制图像,滤除大小或太大的像素值,k为阈值
主要代码如下,运行结果如图9所示:
//二值化函数 void CMFC_DEMODlg::ImageEZH1() { Mat huidu; newform2 Dl; if (Dl.DoModal() == IDOK) { int k = Dl.canshu; cvtColor(image, huidu, COLOR_BGR2GRAY); threshold(huidu, out, k, 255, CV_THRESH_BINARY); ShowPic_2(out); } }
图9:二值化
灰度变换
灰度变换是图像增强的一种重要手段,用于改善图像显示效果,属于空间域处理方法,它可以使图像动态范围加大,使图像对比度扩展,图像更加清晰,特征更加明显。灰度变换其实质就是按一定的规则修改图像每一个像素的灰度,从而改变图像的灰度范围。常见的灰度变换图像反转,对数变换和伽马变换等。其具体分类如下图10所示:
图10:灰度变换分类
(1)均值滤波
均值滤波是对是对信号进行局部平均, 以平均值来代表该像素点的灰度值
主要代码如下:
//均值滤波 void CMFC_DEMODlg::ImageJZ1() { newform6 D; if (D.DoModal() == IDOK) { int k = D.n; //Mat junzhi,out2; out.create(image.size(), image.type()); blur(image, out, Size(k, k)); ShowPic_2(out); } }
(2)高斯滤波
由于高斯函数的傅立叶变换仍是高斯函数, 因此高斯函数能构成一个在频域具有平滑性能的低通滤波器。可以通过在频域做乘积来实现高斯滤波
主要代码如下:
//高斯滤波 void CMFC_DEMODlg::ImageGS1() { newform6 D; if (D.DoModal() == IDOK) { int k = D.n; GaussianBlur(image, out, Size(k,k), 0, 0); ShowPic_2(out); } }
(3)拉普拉斯滤波
由于拉普拉斯是一种微分算子,它的应用可增强图像中灰度突变的区域,减弱灰度的缓慢变化区域。
主要代码如下:
//拉普拉斯 Mat CMFC_DEMODlg::ImageLPLS1() { Mat lpls; Mat K = (Mat_<double>(3, 3) << -1, -1, -1, -1, 9, -1, -1, -1, -1); filter2D(image, lpls, image.depth(), K); return lpls; }
边缘检测
梯度:像素灰度值变化的速度
canny边缘检测:目的是寻找一个最优的边缘,运行图像如图11所示:
最优的边缘定义为:
1.好的检测--算法能够尽可能的标识出图像中的实际边缘
2.好的定位--标识出的边缘要与实际图像中的实际边缘尽可能接近
3.最小响应--图像中的边缘只能标识一次,并和可能存在存在的图像噪声不应该标识为边缘
步骤:
1、高斯滤波:去燥(根据待滤波的像素点极其邻域点的灰度值按照高斯公式生成参数规则进行加权平均,这样可以有效去除理想图像中叠加的高频噪声)
2、计算梯度图像与角度图像
slobel算子:
根据像素点上下,左右邻点灰度加权差,再边缘处达到极值这一现象检测边缘,对噪声具有平滑作用,但是边缘定位精度不够高,当对精度要求不是很高时,是一种常用的边缘检测算法
图11:canny边缘检测
直方图
图像的直方图:指具有某种灰度级的像素的个数,反应图像中每种灰度出现的频率
直方图均衡化:是间接增减对比度的方法之一,主要把给定图像的直方图分布改变为“均匀”分布。原理是:对个数多的灰度级进行展宽,对个数少的灰度级进行缩减,把原始图像的灰度直方图从比较集中的某灰度区间在全部灰度范围内的均匀分布,从而达到清晰图像目的
主要流程如图12所示,显示如图13所示:
图12:直方图流程图
图13:直方图显示
混沌加密
混沌:混沌是一种复杂的动力学行为,不是简单的无序,它没有明显的周期和对称,其内部结构丰富是非线性系统的一种新形式。
Li- Yorke定义:
对于闭区间J,R,设连续映射J—J,如果存在不可数集S J,满足:
1、S不含周期点
2、对任意的两个点p,q∈S(p≠q)
3、对任意p∈S及周期点q∈J,且p≠q
称F映射在S上是混沌的
超混沌:一般混沌系统是一种典型的三维现象,其特点是只有一个正的李雅普诺夫指数,其运动轨迹只在某个方向上产生不稳定性。在自然界中普遍存在高维非线性系统,它们有不止一个正的李雅普诺夫指数,其运动轨迹在两个以上的方向出现指数型的发散轨迹,这种混沌态被称为超混沌
超混沌加密:对称加密,处理速度和密钥长度无关,运行显示如图14所示:
图14:混沌加密
打开摄像头
使用OPENCV打开摄像头,并显示到指定控件中:
主要代码如下,运行结果如图15所示:
// 实时视频处理 static void refineSegments(const Mat& img, Mat& mask, Mat& dst); void CMFC_DEMODlg::VIDEO_deal_fun() { bool update_bg_model = true; Mat tmp_frame, bgmask, out_frame, foreground, bw, gray;; cap.open(0); if (!cap.isOpened()) { AfxMessageBox("打开摄像头失败!"); exit(-1); } cap >> tmp_frame; if (tmp_frame.empty()) { AfxMessageBox("读取帧失败!"); exit(-1); } Ptr<BackgroundSubtractorMOG2> bgsubtractor = createBackgroundSubtractorMOG2(); bgsubtractor->setVarThreshold(10); for (;;) { cap >> tmp_frame; if (tmp_frame.empty()) break; bgsubtractor->apply(tmp_frame, bgmask, update_bg_model ? -1 : 0); ShowPic_1(tmp_frame); } }
图15:打开摄像头
视频灰度化和模糊化和边缘检测
(1)灰度化
主要代码如下:
//灰度化 cvtColor(tmp_frame, out_frame, CV_BGR2GRAY); ShowPic_2(out_frame);
(2)模糊化
主要代码如下:
//模糊化 blur(tmp_frame, out_frame, Size(7, 7));//模糊化 ShowPic_2(out_frame);
(3)边缘检测
主要代码如下:
//边缘检测 GaussianBlur(tmp_frame, out_frame, cvSize(3,3), 2, 2, BORDER_DEFAULT);//高斯平滑 Canny(tmp_frame, out_frame,20,100,3); ShowPic_2(out_frame);
清除背景分割
主要代码如下,运行结果如图16所示:
来源:链接
static void refineSegments(const Mat& img, Mat& mask, Mat& dst) { int niters = 3; vector<vector<Point> > contours; vector<Vec4i> hierarchy; Mat temp; dilate(mask, temp, Mat(), Point(-1, -1), niters); // 膨胀:求核区域像素最大值,可以填补凹洞 erode(temp, temp, Mat(), Point(-1, -1), niters * 2); // 腐蚀:求核区域最小值,能消除凸起 dilate(temp, temp, Mat(), Point(-1, -1), niters); // 膨胀:求核区域像素最大值,可以填补凹洞 findContours(temp, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE); // 轮廓提取 dst = Mat::zeros(img.size(), CV_8UC3); if (contours.size() == 0) return; int idx = 0, largestComp = 0; double maxArea = 0; for (; idx >= 0; idx = hierarchy[idx][0]) { const vector<Point>& c = contours[idx]; double area = fabs(contourArea(Mat(c))); // 求绝对值 if (area > maxArea) { maxArea = area; largestComp = idx; } } Scalar color(0, 0, 255); //将图像设置成单一灰度和颜色 drawContours(dst, contours, largestComp, color, FILLED, LINE_8, hierarchy); // 轮廓填充 }
图16:清除背景分割
存在的问题
1、主窗口关闭不掉,内部有退出按钮,但只能强行关闭窗口,需要手动杀死进程
2、对于实时图像处理的功能,只用了简单地 if-else 进行切换,不存在实用价值,且演示顺序只能为:灰度化、模糊化、边缘检测、清除背景分割。
3、opencv调用摄像头是存在诸多问题,以及始终实现不了加载视频,我太菜!
基于Opencv的简单图像处理的更多相关文章
- 基于qml创建最简单的图像处理程序(3)-使用opencv&qml进行图像处理
<基于qml创建最简单的图像处理程序>系列课程及配套代码基于qml创建最简单的图像处理程序(1)-基于qml创建界面http://www.cnblogs.com/jsxyhelu/p/83 ...
- 基于 opencv 的图像处理入门教程
前言 虽然计算机视觉领域目前基本是以深度学习算法为主,但实际上很多时候对图片的很多处理方法,并不需要采用深度学习的网络模型,采用目前成熟的图像处理库即可实现,比如 OpenCV 和 PIL ,对图片进 ...
- 基于Opencv和Mfc的图像处理增强库GOCVHelper(索引)
GOCVHelper(GreenOpen Computer Version Helper )是我在这几年编写图像处理程序的过程中积累下来的函数库.主要是对Opencv的适当扩展和在实现Mfc程序时候的 ...
- 图像处理基础(2):自适应中值滤波器(基于OpenCV实现)
本文主要介绍了自适应的中值滤波器,并基于OpenCV实现了该滤波器,并且将自适应的中值滤波器和常规的中值滤波器对不同概率的椒盐噪声的过滤效果进行了对比.最后,对中值滤波器的优缺点了进行了总结. 空间滤 ...
- C++从零实现简单深度神经网络(基于OpenCV)
代码地址如下:http://www.demodashi.com/demo/11138.html 一.准备工作 需要准备什么环境 需要安装有Visual Studio并且配置了OpenCV.能够使用Op ...
- Python图像处理丨基于OpenCV和像素处理的图像灰度化处理
摘要:本篇文章讲解图像灰度化处理的知识,结合OpenCV调用cv2.cvtColor()函数实现图像灰度操作,使用像素处理方法对图像进行灰度化处理. 本文分享自华为云社区<[Python图像处理 ...
- [转载]卡尔曼滤波器及其基于opencv的实现
卡尔曼滤波器及其基于opencv的实现 源地址:http://hi.baidu.com/superkiki1989/item/029f65013a128cd91ff0461b 这个是维基百科中的链接, ...
- OpenCV 编程简单介绍(矩阵/图像/视频的基本读写操作)
PS. 因为csdn博客文章长度有限制,本文有部分内容被截掉了.在OpenCV中文站点的wiki上有可读性更好.而且是完整的版本号,欢迎浏览. OpenCV Wiki :<OpenCV 编程简单 ...
- OpenCV2学习笔记(十四):基于OpenCV卡通图片处理
得知OpenCV有一段时间.除了研究的各种算法的内容.除了从备用,据导游书籍和资料,尝试结合链接的图像处理算法和日常生活,第一桌面上(随着摄像头)完成了一系列的视频流处理功能.开发平台Qt5.3.2+ ...
随机推荐
- 16_Android的数据存储_ SharedPreference、XML和JSON
1. Android读写首选项 1.1 SharedPreferences SharedPreferences 是一种轻型的数据存储方式,它的本质是基于XML文件存储Key-Value键值对数据,通常 ...
- Python【集合】、【函数】、【三目运算】、【lambda】、【文件操作】
set集合: •集合的创建; set_1 = set() #方法一 set_1 = {''} #方法二 •set是无序,不重复的集合; set_1 = {'k1','k2','k3'} set_1.a ...
- PyQt(Python+Qt)学习随笔:自定义信号在emit发射信号时报错:AttributeError: object has no attribute
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 如果使用自定义信号,一定要记得信号是类变量,必须在类中定义,不能在实例 ...
- PyQt(Python+Qt)学习随笔:model/view架构中的排序和代理模型QSortFilterProxyModel
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 在Model/View体系架构中,有两种方法可以进行排序:选择哪种方法取决于底层模型. 如 ...
- 关于我 About Me
重庆某大学计算机专业大三学渣 CTF酱油选手 web安全菜鸡 SRC低危小子 精通多门语言 hello world 输出 和 windows linux单词拼写 扣扣:MjU4NTYxNDQ2NA== ...
- 冲刺Day7
每天举行站立式会议照片: 昨天已完成的工作: 1.确认商品分类栏,并前后端交互 2.检查.更正订单模块的代码 3.检查.更正用户模块的代码 今天计划完成的工作: 成员 任务 高嘉淳 检查代码.提供测试 ...
- WPF中DatePiker值绑定以及精简查询
WPF中DatePiker值绑定以及精简查询 1.WPF中DatePiker值绑定 Xaml中值绑定使用Text <DatePicker Text="{Binding strMinDa ...
- CF500G / T148321 走廊巡逻
题目链接 这题是 Codeforces Goodbye 2014 的最后一题 CF500G,只是去掉了 \(u \not= x, v \not = v\) 的条件. 官方题解感觉有很多东西说的迷迷瞪瞪 ...
- Aizu2970 Permutation Sort
题目大意 给你两个 \(n\) 个整数的排列,第一个排列表示原排列,第二个排列表示第 \(i\) 个数可以和i变成第 \(g_i\) 个数,问,最少对所有数进行几次操作可以使原排列变为有序的排列. 题 ...
- shell--数据库备份脚本
#!/bin/bash #数据库的完全备份 #把日期显示为170605(这个是当前的时间)的格式 date=$(date +%y%m%d) #计算下这个备份的数据库文件的大小 size=$(du -s ...