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的 ...
随机推荐
- AJ学IOS(32)UI之Quartz2D矩阵操作和图片剪切
AJ分享,必须精品 矩阵操作 矩阵操作:(旋转,缩放,平移) 通过矩阵操作,把画出来的东西进行形变 旋转操作 方法:CGContextRotateCTM(<#CGContextRef c#> ...
- d3.js v4曲线图的拖拽功能实现Zoom
zoom缩放案例 源码:https://github.com/HK-Kevin/d...:demo:https://hk-kevin.github.io/d3...: 原理:通过zoom事件来重新绘制 ...
- Bug Bash in Personal Photo Experience 1/11/2016
In the process of our Personal Photo Experience Project, There are some bugs which hinder our forwar ...
- python圆周率计算小程序(非常慢)
源码: from math import fabs #导入数学模块 from time import perf_counter #导入时间模块 from numba import jit @jit d ...
- Linux相关操作
ssh配置秘钥 连接远程服务器时:需要用户持有“公钥/私钥对”,远程服务器持有公钥,本地持有私钥. 客户端向服务器发出请求.服务器收到请求之后,先在用户的主目录下找到该用户的公钥,然后对比用户发送过来 ...
- Linux学习笔记(七)关机、重启及常用的网络命令
关机.重启命令 sync shutdown reboot init sync 英文原意:flush file system buffers 功能:刷新文件系统缓冲区,将内存中的数据保存到硬盘中 语法: ...
- 吃瓜的正确姿势,Python绘制罗志祥词云图
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 这篇文章中向大家介绍了Python绘制词云的方法,不难看出绘制词云可以说是一 ...
- Spring5:事务管理【整合Mybatis】
Spring 整合Mybatis 1:导入依赖 <dependencies> <!--测试依赖--> <dependency> <groupId>jun ...
- 关于JavaEE中Spring模块的学习!
七大模块,如下: 1. Spring Core: Core封装包是框架的最基础部分,提供IOC和依赖注入特性.这里的基础概念是BeanFactory,它提供对Factory模式的经典实现来消除对程序性 ...
- 【AspNetCore源码】设计模式 - 提供者模式
AspNetCore源代码发现日志模块的设计模式(提供者模式),特此记录 学习设计模式的好处是,我们可以容易扩展它达到我们要求,除了要知道如何扩展它,还应该在其他地方应用它 类图 & 分析 角 ...