插件文档描述 简单的矩形示例
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OpenCVForUnity.ImgprocModule;
using OpenCVForUnity.ImgcodecsModule;
using OpenCVForUnity.CoreModule;
using Rect = OpenCVForUnity.CoreModule.Rect;
using OpenCVForUnity.UnityUtils;
using UnityEngine.UI;
public class TestOpenCv : MonoBehaviour
{
public RawImage rawImage;
void Start()
{
Mat mat= Imgcodecs.imread(Application.streamingAssetsPath + "/pca_test1.jpg",1);
List<Mat> channels = new List<Mat>();
Mat mat2 = channels[2];
channels[2] = channels[0];
channels[0] = mat2;
Imgproc.rectangle(mat, new Point(10, 10), new Point(200, 200), new Scalar(255, 0, 0, 255), 5);
Texture2D texture = new Texture2D(mat.cols(), mat.rows(), TextureFormat.RGBA32, false);
Utils.matToTexture2D(mat, texture);
rawImage.texture = texture;
}
}
// Mat 基本图像容器 不知道mat作用的可以阅读一下https://www.w3cschool.cn/opencv/opencv-bedc2caa.html
静态方法方法 | 描述 |
---|
Imgcodecs.imread(filename,flags) | 读取一张图像 返回Mat对象 flags默认为彩色图像,1为彩色,0为灰度值 | Imgcodecs.imwrite(filename,mat,MatOfInt) | 保存图像 其中 MatOfInt 参考下文 | Imgproc.cvtColor() | 将图像从一种颜色空间转换为另一种颜色空间 可以参数OpenCVForUnityExample场景使用Imgproc.COLOR_BGR2RGB | Imgproc.rectangle | 绘制一个简单的矩形框,参考MatchTemplateExample | Imgproc.resize() | 函数调整大小将图像 src 调整为指定大小 如果size为0 fx,fy是沿着x,y方向伸缩 比如fx=1,fy=2,fx不变 fy放大两倍,也可以设置具体的size值 | Imgproc.threshold | 图像阈值 dst输出图像 thresh阈值 maxval当像素超过阈值或者小于阈值时所赋予的值,type==>Imgproc.THRESH_OTSU参考在下面 | Imgproc.blur | 图像平滑操作 卷积概念 比如一个图像有噪音点,想要去除这些点,ksize为核的大小比如[3,3],周围3*3个像素点为一组,默认point(-1,-1)为核中心点,borderType 用于推断图像外的像素 | Imgproc.boxFilter | 方框滤波基本上与blur差不多normalize=true 归一化,如果为false 如果色域大于255则直接取255 | Imgproc.GaussianBlur | 高斯滤波 其它像素点离中心点像素点越近权重越大,效果比均指滤波好 | Imgproc.medianBlur | 中值滤波,找寻其核里中间的值 | Imgproc.erode | 结构元素腐蚀源图像,参考在下面 | Imgproc.dilate | 扩展图像或者像素膨胀,跟erode相反,相当于shader中顶点沿着法线方向膨胀 | Imgproc.morphologyEx | 把图像的腐蚀操作和膨胀操作合为一起,开闭运算,其中op参数可以参考Imgproc.MORPH_OPEN这些值,MORPH_OPEN 先腐蚀再膨胀,MORPH_CLOSE 先膨胀再腐蚀,MORPH_GRADIENT 梯度运算 膨胀-腐蚀得到一个轮廓,MORPH_TOPHAT 原始输入-开运算结果(MORPH_OPEN),MORPH_BLACKHAT 闭运算(MORPH_CLOSE)-原始输入得到大致的轮廓.其它参数跟上面的差不多 | Imgproc.Sobel | 梯度算子 找出色素区域差异大的像素点 | Imgproc.Scharr | 也是一个图像边缘检测 比sobel显示的色彩更丰富一点 | Imgproc.Laplacian | 拉普拉斯算子 具体呈现效果自己试验 比sobel显示的色彩少一点 | Imgproc.Canny | Canny 算法查找图像中的边缘,参数 dx 和dy输入图像的 16 位 x 导数(CV_16SC1 或 CV_16SC3), 参数edges是输出边缘图,单通道 8 位图像,参数threshold1和threshold2是阈值用来确定真实和潜在的边缘 | Imgproc.pyrUp | 对图像进行上采样,然后对其进行模糊处理,该函数执行高斯金字塔构造的上采样步骤,它实际上可以用于构造拉普拉斯金字塔。首先,它通过注入零行和零列对源图像进行上采样,然后使用与 pyrDown 乘以 4 相同的内核对结果进行卷积,输出图像的大小计算为 {code Size(src.cols2, (src.rows2)} | Imgproc.pyrDown | 计算公式code Size((src.cols+1)/2, (src.rows+1)/2) 图像向下采样 | Core.split(mat, channels) | 获取颜色通道的值rgb | Core.merge | 可以与上面Core.split一起使用,修改为各通道值后在合并为rgb | Core.copyMakeBorder | 边界填充 参数:上下左右分别填充多少以及对应的色值(Scalar) 和填充方式(borderType) | Core.add() | 计算两个数组或一个数组和一个标量的每个元素的总和。大于255 取255的值 | Core.addWeighted() | 两个图片融合 alpha为src1的权重 ,beta为src2的参数,加上一个亮度值gamma,公式dst = src1×alpha + src2×beta + gamma | Core.convertScaleAbs | 缩放、计算绝对值并将结果转换为 8 位 |
动态方法 | 描述 |
---|
Mat.size() | 获取图片像素点个数,也可以传入int值返回size的其中一个值,默认返回cols, rows两个值 | Mat.setTo() | 将所有或部分数组元素设置为指定值。 | VideoCapture.open | 打开视频文件流,返回bool 是否成功 | VideoCapture.isOpened() | 是否能打开视频流 | VideoCapture.read | 读取每一帧 返回bool 是否读取成功 | VideoCapture.get | 得到详情信息,比如格式 fps | VideoCapture.release | 如果这个视频不需要,卸载当前内存的意思 |
创建mat的类型 Type (Core.CV_8U)
MatOfInt
16 位无符号 (CV_16U) 图像可以保存为 PNG、JPEG 2000 和 TIFF 格式 32 位浮点 (CV_32F) 图像可以保存为 PFM、TIFF、OpenEXR 和 Radiance HDR 格式;将使用 LogLuv 高动态范围编码(每像素 4 字节)保存 3 通道 (CV_32FC3) TIFF 图像 使用此功能可以保存带有 Alpha 通道的 PNG 图像。为此,请创建 8 位(或 16 位)4 通道图像 BGRA,其中 Alpha 通道在最后。完全透明的像素应将 alpha 设置为 0,
string format = "jpg";
MatOfInt compressionParams = new MatOfInt(1, 100);
string format = "png";
MatOfInt compressionParams = new MatOfInt (16, 0);
VideoCapture
使用 API 打开视频文件或捕获设备或 IP 视频流以进行视频捕获
VideoCapture capture = new VideoCapture ();
capture.open (Utils.getFilePath (VIDEO_FILENAME));
(1) get方法 VideoCapture.get()
参数 Videoio.CAP_PROP_FORMAT,Videoio.CAP_PROP_POS_MSEC等可以找到这些目标值,根据需要取得
BorderTypes
阈值 (Imgproc.threshold)
Src输入图只能输入单通道图像,通常来说是灰度图
Imgproc.threshold(mat, mat, 127, 255, Imgproc.THRESH_BINARY);
比如这个示例 大于127的取白色,小于127的取黑色
1.Imgproc.CV_THRESH_BINARY 当像素超过阈值去maxval,否则取0 2.Imgproc.CV_THRESH_BINARY_INV 与上面的相反 3.Imgproc.CV_THRESH_TRUNC 大于阈值的部分设为阈值,否则不变 4.Imgproc.CV_THRESH_TOZERO 大于阈值的部分不变,否则设为0 5.Imgproc.CV_THRESH_TOZERO_INV 与上面4的相反
图像腐蚀操作 (Imgproc.erode)
一.Imgproc.erode (Mat src,Mat dst,Mat kernel,Point anchor,int iterations,int borderType,Scalar borderValue ) 二.Imgproc.erode ( Mat src,Mat dst,Mat kernel,Point anchor,int iterations,int borderType )
1.iterations为迭代系数 2.borderValue 边界值在恒定边界 3.kerne= Mat.ones(30 ,30, CV_8U) 用于侵蚀的核结构元素 size[30,30]使用 30*30矩形结构元素构成
Mat kerne= Mat.ones(30 ,30, CV_8U)
Imgproc.erode(src,dst,kerne,new Point(-1,-1),1)
Imgproc.erode(src,dst,kerne,new Point(-1,-1),1)
Imgproc.erode(src,dst,kerne,new Point(-1,-1),2)
Imgproc.erode(src,dst,kerne,new Point(-1,-1),2)
迭代图对比
边缘检测
简单列举两个具体实现都差不多
梯度算子(Imgproc.Sobel)
A为核的大小[3,3],Gx为像素点水平方向的梯度算子,Gy是垂直方向,其中[-1,0,+1,-2,0,+2,-1,0,+1]这些值是卷积核与矩阵A相乘 Imgproc.Sobel ( Mat src,Mat dst,int ddepth,int dx,int dy,int ksize,double scale,double delta,int borderType ) mat在 8 位输入图像的情况下,它将导致截断导数 ddepth 为图像深度 通常为-1 dx和dy 分别为水平和垂直方向 Gx Gy 比如dx=1 dy=0,那么表示只算水平方向的正值 ksize 是sobel算子的大小 [3,3] 其值设为1、3、5 或 7
Canny算子 (Imgproc.Canny)
1.使用高斯滤波器,处理图像的噪声 2.计算每个梯度的强度和方向 G=sqre(Gx2,Gy2) ,θ=arctan(Gy/Gx) 他们的核与sobel一样 3.非极大值抑制 比较这个点与周围点的大小,如果是最大的则保存下来,如果不是则抑制掉 4.双阈值 梯度值>maxvalue:则处理为边界,梯度值<minvalue:则舍弃,minVal<梯度值<maxVal 跟边界点连接的则保留否则舍弃
void TestSobel()
{
Texture2D matchshapes = Resources.Load("matchshapes") as Texture2D;
Mat mat = new Mat(matchshapes.height, matchshapes.width, CvType.CV_8U);
Utils.texture2DToMat(matchshapes, mat);
Mat dst1=new Mat();
Imgproc.Sobel(mat, dst1, -1, 0, 2, 3);
Mat dst2= new Mat();
Imgproc.Sobel(mat, dst2, -1, 2, 0, 3);
Core.addWeighted(dst1, 0.5, dst2, 0.5, 0, mat);
Texture2D texture = new Texture2D(mat.cols(), mat.rows(),TextureFormat.BGRA32, false);
Utils.matToTexture2D(mat, texture);
rawImage.texture = texture;
}
void TestCanny()
{
Mat mat= Imgcodecs.imread(Application.streamingAssetsPath + "/lena.jpg", 0);
Debug.Log(mat);
Mat mat1 = Mat.ones(mat.size(), CvType.CV_8UC1);
Imgproc.Canny(mat, mat1, 80, 120);
Texture2D texture = new Texture2D(mat1.cols(), mat1.rows(), TextureFormat.BGRA32, false);
Utils.matToTexture2D(mat1, texture);
rawImage.texture = texture;
Texture2D texture1 = new Texture2D(mat.cols(), mat.rows(), TextureFormat.BGRA32, false);
Utils.matToTexture2D(mat, texture1);
GetRaw.texture = texture1;
}
|