openCV从入门到放弃
与图像处理之间的关系,opencv的简介和使用定位
一些基本的知识
去噪点 ,其实就是模糊化 让毛刺高波跟周围像素平均 也叫均值滤波 低通滤波。锐化,其实就是让毛刺像素加上跟周围的方差 这样大的被放大 也叫高通滤波 ,可以让边缘更明显。颜色空间的处理 ,简易理解可理解为直方图处理 ,可理解为上面一样,理论化的说 跟书上说的一样也就是波处理。让某一部分波不可见 而把另一部分拉伸到0~255的范围 让特征部分对比更明显 不至于浪费输出带宽,典型的对比度调整 对比度均匀化 本质都是波处理 ,阈值化 典型的削波处理 ,波处理都是会损失信息的 尤其是阈值化 ,但是我们这样做的目的是 让计算机更容易判别 比如轮廓识别。
openCV基本使用
Mat src = Cv2.ImRead("lena.jpg");//new Mat("lena.jpg", ImreadModes.Color);
//对颜色矩阵进行变换
//Mat src2= src.CvtColor(ColorConversionCodes.RGB2GRAY);
//输出变换后的矩阵数据 发现就变成灰度的了
//Cv2.ImShow("src", src2); //画一条线段
//这里要求的参数是inputArray ,其实可以简单的当做Mat类型即可 P67
Cv2.Line(src, , , , , new Scalar(, , ));
Cv2.ImShow("src", src);
opencv里面有几种基本的数据类型比如Point Path这些 ,细想一下就能够想得到 ,图像处理 倒腾的是什么 特征 特征 特征 ,这些东西就是来进行数据交互用的,有可能是用作输入 比如你要标注一个ROI区域 ,也有可能是用作opencv输出用的 比如opencv从图中检测出来一个几何图形 给你的反馈。好接下来我们演示一下简单的标注 图像叠加混合 转存。
Mat image = new Mat("lena.jpg");
Mat logo = new Mat("car.jpg");
//定义一个mat类型 用于存放图像的ROI
//方法1
//好像在某篇帖子上是说过 ROI感兴趣区域是用mat定义的,然后缩放还是裁剪的时候是会以此为参照 //把lena图的感兴趣区域设置为小图大小?
//基本理念
//实质上是通过image 结合Rect建立了一个选区 ,其实操作还是操作的原来的像素,
//对原图的影响始终超不出此区域(注意imgROI并不是一块独立的数据区域)
Mat imageROI = new Mat(image, new Rect(, , logo.Cols, logo.Height)); //把小图叠加到原图的感兴趣区域?
//注意 操作后 imageROI的图像是小图大小 通过透明混合了两幅图(原图和 imageROI都操作了)
Cv2.AddWeighted(imageROI, , logo, 0.3, , imageROI);//此方法必须两个图宽高一致 //这是网上的代码 c++的构造器代码套路方式 ,通过一个对象作为参数创建一个对象
// Mat src = imread("test.jpg");
// Mat logo = imread("logo.jpg");
////设定ROI区域
//Mat ROI = src(Rect(20, 25, logo.cols, logo.rows));//注意这边Rect函数,先列后行(长*高(宽)) //注意
imageROI.Line(, , , , new Scalar(, , )); //int[] compression_params = new int[2];
//compression_params[0] = (int)OpenCvSharp.ImwriteFlags.PngCompression;
//compression_params[1] = 9;
//imageROI.ImWrite("ROI混合区域.png", compression_params);
//image.ImWrite("叠加.png", compression_params); Cv2.ImShow("叠加", image);
Mat srcImage1 = new Mat("car.jpg");
Mat srcImage2 = new Mat("ship.jpg");
float g_dalphaValue = (float)trackBar1.Value/(float)trackBar1.Maximum;
float g_dBetaValue = 1.0f - g_dalphaValue;//1.0f;//
//根据alpha 和beta进行线性混合
Mat dstImage = new Mat();
Cv2.AddWeighted(srcImage1, g_dalphaValue, srcImage2, g_dBetaValue, 0.0, dstImage); Bitmap dstBmp = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dstImage);
pictureBox1.Image = dstBmp;
效果:
ROI也就是感兴趣区域,只要标定过后然后整个操作都只影响这个区域范围(注意图中画的红色线段是从小图ROI区域开始的)。整个过程中进行对象分割然后分块处理降低整体图像对算法的效果影响 ,这也是图像处理里面的常规套路。
太无聊了,来点稍微有丁点意思的
来点稍微有丁点意思的,是的让你体会到人类智慧以及计算机的神奇之处哇哈哈哈哈,注意这里的有意思之处是来源于opencv底层的几何检测函数功能 说白了我们只是个搬砖的 如果你更有脾气一点 你应该把检测的原理搞懂。好 我们要做的是检测图像中的所有几何图形 有哪些是一类的 我们把它标注出来,用到了上面讲的opencv基本套路和概念。
public void ShapeMatchTest()
{
Mat src = Cv2.ImRead("shape4.png");
Mat src2 = src.CvtColor(ColorConversionCodes.RGB2GRAY);
Mat src3 = src2.Threshold(, , ThresholdTypes.BinaryInv);//THRESH_BINARY_INV Mat[] findeds; //用于存储轮廓的?
OpenCvSharp.Point[][] contours;
HierarchyIndex[] hierarchy;// Vec4i[]错误 9 参数 2: 无法从“out OpenCvSharp.Vec4i[]”转换为“out OpenCvSharp.Hier // Mat[] contours2;
//Mat hierarchy2 = new Mat(); //找出并显示了所有轮廓 ,注意并不是一个完整的路径 标识一个轮廓 而是二维数组
src3.FindContours(out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple);
//src3.FindContours(out contours2, hierarchy2, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple); //for (int i = 0; i < contours2.Length; i++)
//{
// src.DrawContours(contours2[i], contours2,i, new Scalar(0, 255, 0), 3);
//}
Bitmap resultImg = MatCopyToBmp(src); //显示轮廓点 事实证明 每个contours[i] 是一个路径 ,并且每个路径里面的点是顺序排列的
System.Drawing.Graphics g = Graphics.FromImage(resultImg);
//DrawBmpContours(g, contours);
// ret = cv2.matchShapes(k0,c0,1,0.0)
// cv2.drawContours(img,[c0],-1,(0,255,0),2) //对所有相近轮廓进行归类 双重list
List<List< OpenCvSharp.Point[]>> matched = new List<List<OpenCvSharp.Point[]>>();
OpenCvSharp.Point[][] contours2 = (OpenCvSharp.Point[][])contours.Clone(); //首先把第一个轮廓归为一组
matched.Add(new List<OpenCvSharp.Point[]>() { contours[]}); for (int i = ; i < contours.Length; i++)//直接从第二个开始
{
//假定没匹配到
bool matchedok=false;
//在已经归好类的组里面找
for (int j = ; j < matched.Count; j++)
{
//当前跟归好类的匹配 因为一类的都是一样的所以只匹配第一个
var ret = Cv2.MatchShapes(contours[i], matched[j][], ShapeMatchModes.I1, 0.0);
Console.WriteLine(ret);
//<0.05基本上可以准确区分
//shape.png <1可区分正方形三角形
//数值越大区分能力越弱
//0.2基本可区分锐角三角形 钝角三角形 (正方形 包括旋转了的) ,区分能力已经较弱
if (ret <0.1)
{
//如果匹配上则往那一类里面归
matchedok=true;
matched[j].Add(contours[i]);
break;
}
}
//如果当前的跟以前的所有的都没匹配上则另启一组
if(matchedok==false){
matched.Add(new List<OpenCvSharp.Point[]>() { contours[i]});
}
}
//只绘制相似的图形
//OpenCvSharp.Point[][] contoursMatched = new OpenCvSharp.Point[matched.Count][];
//for (int i = 0; i < contoursMatched.Length; i++)
//{
// src.DrawContours(contoursMatched, i, new Scalar(0, 255, 0), 3);
//} Scalar[] scars = new Scalar[]{
new Scalar(,,),
new Scalar(,,),
new Scalar(,,),
new Scalar(,,),
new Scalar(,,),new Scalar(,,),
new Scalar(,,)}; Console.WriteLine(matched.Count + "组");
int scrindx=;
for (int i = ; i < matched.Count; i++)
{
Random rdm = new Random();
Scalar cor = scars[(++scrindx)%];//new Scalar(rdm.Next(1, 255), rdm.Next(1, 255), rdm.Next(1, 255));
for (int j = ; j < matched[i].Count; j++)
{
src.DrawContours(matched[i], j, cor, );
}
} //绘制结果到窗体
Graphics gForm = Graphics.FromHwnd(this.Handle);
gForm.DrawImage(resultImg, new PointF(, ));
Cv2.ImShow("hahaha", src);
}
效果图:
经过一段时间的学习呢,最后我的工作也完成了,由于特征比较明显算法本身难度不是想象的那么大 opencv呢太重了,所以最终没有用到任何第三方的库,提前祝大家端午节愉快。。。
总结
以前我用GDI+的SetPixel()处理像素不是被人骂吗,实际上opencv这玩意儿要说的话照我的就是可以理解为一个 进行像素处理 的 “效率工具” 并且我试过了写的也确实很牛逼 算法的效率很高。并且自带有一些图像处理的惯用套路 和算法在里面 算法的参数调节 数据展现都是蛮方便的 特别是mat矩阵数据跟API无缝结合的设计。然后能搞懂一些数学知识是最好,最不济也必须学习一些图像处理的基本概念。有些算法可以不用完全搞懂原理 但是得搞懂大概的过程 否则调参数你不知道怎么调对最终结果会产生什么影响,然后自己模拟一个过程 通过opencv的多个函数相结合就能达到想要的效果比如低通滤波然后腐蚀在某些图就能够达到对象分割。总之opencv理解为自动化图像处理的 “效率工具”
openCV从入门到放弃的更多相关文章
- OpenCV从入门到放弃系列之——如何扫描图像、利用查找表和计时
目的 如何遍历图像中的每一个像素? OpenCV的矩阵值是如何存储的? 如何测试我们所实现算法的性能? 查找表是什么?为什么要用它? 测试用例 颜色空间缩减.具体做法就是:将现有颜色空间值除以某个输入 ...
- OpenCV从入门到放弃系列之——core模块.核心功能(一)
Mat - 基本图像容器 世间的图像是各种各样的,但是到了计算机的世界里所有的图像都简化为了数值矩以及矩阵信息.作为一个计算视觉库,OpenCV的主要目的就是处理和操作这些信息,来获取更高级的信息,也 ...
- OpenCV从入门到放弃系列之——图像的基本操作
读取.修改.保存图像 图像读取函数imread(); 图像颜色空间的转换cvtColor(); 图像保存至硬盘imwrite(); /********************************* ...
- OpenCV从入门到放弃(五):像素!
一.概念 1.图像本质上面是由数值组成的矩阵.矩阵中的一个元素相应一个像素. 2.对于灰度图像(黑白图像),像素是8位无符号数(CV_8U).0表示黑色,255表示白色.对于彩色图像,是用三原色数据合 ...
- CYQ.Data 从入门到放弃ORM系列:开篇:自动化框架编程思维
前言: 随着CYQ.Data 开始回归免费使用之后,发现用户的情绪越来越激动,为了保持这持续的激动性,让我有了开源的念头. 同时,由于框架经过这5-6年来的不断演进,以前发的早期教程已经太落后了,包括 ...
- [精品书单] C#/.NET 学习之路——从入门到放弃
C#/.NET 学习之路--从入门到放弃 此系列只包含 C#/CLR 学习,不包含应用框架(ASP.NET , WPF , WCF 等)及架构设计学习书籍和资料. C# 入门 <C# 本质论&g ...
- OpenStack从入门到放弃
OpenStack从入门到放弃 目录: 为何选择云计算/云计算之前遇到的问题 什么是云计算 云服务模式 云应用形式 传统应用与云感知应用 openstack及其相关组件介绍 flat/vlan/gre ...
- 绕过校园网的共享限制 win10搭建VPN服务器实现--从入门到放弃
一.开篇立论= =.. 上次说到博主在电脑上搭建了代理服务器来绕过天翼客户端的共享限制,然而经过实际测试还不够完美,所以本着生命不息,折腾不止的精神,我又开始研究搭建vpn服务器= =... (上次的 ...
- 《区块链:从入门到放弃》之obc安装步骤
obc安装步骤 朋友们可能会好奇,厨师不研究菜谱怎么改研究兵法了,哈哈,我原本是app出身,最近被安排去预研区块链和比特币技术,2个月下来,颇有斩获.期间得到IBM的CC同学指导我一步一步安装obc的 ...
随机推荐
- MySQL中group_concat函数 --- 很有用的一个用来查询出所有group by 分组后所有 同组内的 内容
本文通过实例介绍了MySQL中的group_concat函数的使用方法,比如select group_concat(name) . MySQL中group_concat函数 完整的语法如下: grou ...
- 基于ffmpeg不同编码方式转码后的psnr对比
一.测试说明: 源文件:1080psrc.mp4 时长:900秒 源文件信息:Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [S ...
- fiddler composer post请求
必加部分:Content-Type: application/json
- Android 程序代码进行代码混淆
1.在Eclipse项目包下的project.properties文件中加入proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt ...
- Ansible简明教程
Ansible是当下比较流行的自动化运维工具,可通过SSH协议对远程服务器进行集中化的配置管理.应用部署等,常结合Jenkins来实现自动化部署. 除了Ansible,还有像SaltStack.Fab ...
- stand up meeting 12-4
今日进步: 1.国庆答题界面和结果界面的连接完成,并能显示GetRankData API返回结果和错误题目的单词信息. 2.天赋: 完成了整个 单词挑战需要碰到的"Storage" ...
- 2019CCPC-江西省赛(重现赛)- 感谢南昌大学
A题: 题意: 给你两棵树,然后用一条边将这两棵树连接起来,然后计算 每两点之间的距离,然后求和,问这个和的最小值. 思路:根据重心的性质,树上的所有点到重心的距离最短,因此我们找到两棵树的重心,然后 ...
- 带权值的图 BFS
用bfs遍历最图求最短路径时通常借用优先队列即优先考虑最大的或者最小的权值 方法1 优先队列:(内置函数,优先考虑较小的权值) #include<iostream> #include< ...
- C - Highways poj1751最小生成树
The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has a very poor system of p ...
- 在vue中使用ztree树插件
插件资源及api:树官网 本事例是在vue3.0+中演示,事例是实际项目中正在用的组件所以部分打了马赛克. 1.插件准备(提前准备好插件文件) 可以直接在官网下载,搭建好脚手架后将准备好的文件放在li ...