与图像处理之间的关系,opencv的简介和使用定位

如题...因为偶然的机会需要用到图像处理,像我这么爱学习 并且动手能力又强的人怎么能没有心得笔记呢,哇哈哈哈。非要说的low逼点这玩意儿这玩意儿就是像素处理。找出像素中的特征规律 然后根据这些规律去处理数据,就是图像特征处理 不是什么鸟人工智能 不是什么鸟人工智能 不是什么鸟人工只能 重要的话说3遍,但是普遍的商业公司对外宣称却都是吹嘘的啥人工智能高大上的 ,因为像素数据可以理解为信号量,所以是有一些数学理论或者公式能让他更好的工作的理论基础的,基于这里面的理论深度要说的话某些算法也可以达到很高深,所以称之为智能也不为过。数学不好也不要太害怕。实在很半吊子  那也没法 将就着搞吧 ,比如我 哇哈哈哈哈。
 

一些基本的知识

图像的像素数据可以理解为信号量,图像像素之间的坐标关系称之为空域 ,主要手段和理念是图形学 形态学。常见进行对象分割和特征查找的手段有 轮廓查找 霍夫圆 联通区域标定 腐蚀 膨胀 等 都是空域算法,其作用本意都是让空域有意义 进行对象分割 形成有意义的数据。
关于滤波:
去噪点 ,其实就是模糊化 让毛刺高波跟周围像素平均 也叫均值滤波 低通滤波。锐化,其实就是让毛刺像素加上跟周围的方差 这样大的被放大 也叫高通滤波 ,可以让边缘更明显。颜色空间的处理 ,简易理解可理解为直方图处理 ,可理解为上面一样,理论化的说 跟书上说的一样也就是波处理。让某一部分波不可见 而把另一部分拉伸到0~255的范围 让特征部分对比更明显 不至于浪费输出带宽,典型的对比度调整 对比度均匀化 本质都是波处理 ,阈值化 典型的削波处理 ,波处理都是会损失信息的 尤其是阈值化 ,但是我们这样做的目的是 让计算机更容易判别 比如轮廓识别。
 
一些简易而有效的思路也可以使用并不是多高深的数学公式算法 ,比如有干扰线的验证码识别 怎么进行分割 其实可以用 直方图投影。最低值那一部分 也就是最细的那一部分 肯定就是干扰线 ,则可进行分割。 
 
很久以前偶尔看到一直不明白搞那些花里胡哨的的不同色调的玩意儿图像效果到底有神马作用 好看吗,多年后的我好像稍微明白那么一丁点儿了,那些不是给你看的而是给计算机看的。
 
好吧我也不知道我唧唧歪歪说的些啥 ,就当我 就当你们都懂了吧 哇哈哈哈哈。好了咸淡扯完了。接下来opencv使用,其实就直接看那些opencv入门类的书其实就成 但是这玩意儿是C++写的 默认也是c++绑定 。网上代码见得最多就是 python绑定的代码。但是我是懂C++的  ,这不就派上用场了 找了C++的opencv入门教程  结合c++教程里opencv的概念理论 然后找了点python绑定的参考代码 改吧改吧 一周多时间 就搞会了 ,我感觉我膨胀了   哇哈哈哈哈。
 

openCV基本使用

 载入一幅图像,基本理念是像素数据都存储在Mat里面 ,对矩阵进行颜色变换 相当于就是整体颜色更换了一种处理方式。
 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从入门到放弃的更多相关文章

  1. OpenCV从入门到放弃系列之——如何扫描图像、利用查找表和计时

    目的 如何遍历图像中的每一个像素? OpenCV的矩阵值是如何存储的? 如何测试我们所实现算法的性能? 查找表是什么?为什么要用它? 测试用例 颜色空间缩减.具体做法就是:将现有颜色空间值除以某个输入 ...

  2. OpenCV从入门到放弃系列之——core模块.核心功能(一)

    Mat - 基本图像容器 世间的图像是各种各样的,但是到了计算机的世界里所有的图像都简化为了数值矩以及矩阵信息.作为一个计算视觉库,OpenCV的主要目的就是处理和操作这些信息,来获取更高级的信息,也 ...

  3. OpenCV从入门到放弃系列之——图像的基本操作

    读取.修改.保存图像 图像读取函数imread(); 图像颜色空间的转换cvtColor(); 图像保存至硬盘imwrite(); /********************************* ...

  4. OpenCV从入门到放弃(五):像素!

    一.概念 1.图像本质上面是由数值组成的矩阵.矩阵中的一个元素相应一个像素. 2.对于灰度图像(黑白图像),像素是8位无符号数(CV_8U).0表示黑色,255表示白色.对于彩色图像,是用三原色数据合 ...

  5. CYQ.Data 从入门到放弃ORM系列:开篇:自动化框架编程思维

    前言: 随着CYQ.Data 开始回归免费使用之后,发现用户的情绪越来越激动,为了保持这持续的激动性,让我有了开源的念头. 同时,由于框架经过这5-6年来的不断演进,以前发的早期教程已经太落后了,包括 ...

  6. [精品书单] C#/.NET 学习之路——从入门到放弃

    C#/.NET 学习之路--从入门到放弃 此系列只包含 C#/CLR 学习,不包含应用框架(ASP.NET , WPF , WCF 等)及架构设计学习书籍和资料. C# 入门 <C# 本质论&g ...

  7. OpenStack从入门到放弃

    OpenStack从入门到放弃 目录: 为何选择云计算/云计算之前遇到的问题 什么是云计算 云服务模式 云应用形式 传统应用与云感知应用 openstack及其相关组件介绍 flat/vlan/gre ...

  8. 绕过校园网的共享限制 win10搭建VPN服务器实现--从入门到放弃

    一.开篇立论= =.. 上次说到博主在电脑上搭建了代理服务器来绕过天翼客户端的共享限制,然而经过实际测试还不够完美,所以本着生命不息,折腾不止的精神,我又开始研究搭建vpn服务器= =... (上次的 ...

  9. 《区块链:从入门到放弃》之obc安装步骤

    obc安装步骤 朋友们可能会好奇,厨师不研究菜谱怎么改研究兵法了,哈哈,我原本是app出身,最近被安排去预研区块链和比特币技术,2个月下来,颇有斩获.期间得到IBM的CC同学指导我一步一步安装obc的 ...

随机推荐

  1. cmake cpack 安装打包程序

    //set(CPACK_GENERATOR "TGZ") 7Z(.7z) 7Zzip(.7z) TBZ2(tar.bz2) TGZ(.tar.gz) TXZ(.tar.xz) TZ ...

  2. uni-app同步缓存值 设置 读取 删除

    A页面 <view class="go-to-tab" @tap="gotologin"> 去login页面 </view> msg : ...

  3. Spring Cloud 系列之 Gateway 服务网关(一)

    什么是 Spring Cloud Gateway Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由 ...

  4. 使用SVG内置API计算图形或点经过transform之后的新坐标

    一个应用场景是,点击一条路径,显示该路径的控制点.因为有transform变形( 平移.缩放.倾斜.旋转等变换),所以获取变形后的新坐标需要计算. 纯数学的方法,就是用2D变换矩阵的一些公式去运算,过 ...

  5. 泛型方法或泛型类中的方法是内部调用、PInvoke 或是在 COM 导入类中定义的。

    泛型基类中引用Api函数定义时static extern,在子类中会提示: 未处理TypeLoadException 泛型方法或泛型类中的方法是内部调用.PInvoke 或是在 COM 导入类中定义的 ...

  6. Ubuntu安装Elasticsearch6.3

    本文使用的 Ubuntu 版本信息: Distributor ID: Ubuntu Description: Ubuntu LTS Release: 16.04 Codename: xenial 1. ...

  7. yzmsb_test.py

    识别诺诺金服页面的验证码,并自动登录到后台. #导包 from selenium import webdriver from PIL import Image, ImageDraw from time ...

  8. 网站假死 重启NGINX无效 必须重启PHP 原因分析

    一.错误提示说明: Nginx 502 Bad Gateway:请求的PHP-CGI已经执行,但是由于某种原因(一般是读取资源的问题)没有执行完毕而导致PHP-CGI进程终止. Nginx 504 G ...

  9. Shellshock远程命令注入(CVE-2014-6271)漏洞复现

    请勿用于非法用法,本帖仅为学习记录 shelshocke简介: shellshock即unix 系统下的bash shell的一个漏洞,Bash 4.3以及之前的版本在处理某些构造的环境变量时存在安全 ...

  10. Python爬虫篇(代理IP)--lizaza.cn

    在做网络爬虫的过程中经常会遇到请求次数过多无法访问的现象,这种情况下就可以使用代理IP来解决.但是网上的代理IP要么收费,要么没有API接口.秉着能省则省的原则,自己创建一个代理IP库. 废话不多说, ...