插件文檔描述
簡單的矩形示例
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;
// Start is called before the first frame update
void Start()
{
// 定義一個mat
Mat mat= Imgcodecs.imread(Application.streamingAssetsPath + "/pca_test1.jpg",1);
List<Mat> channels = new List<Mat>();
//拆分rgb
// Core.split(mat, channels);
//bgr=>rgb
Mat mat2 = channels[2];
channels[2] = channels[0];
channels[0] = mat2;
//g值為0
// channels[1].setTo(new Scalar(0,0,0,0));
//b值為0
// channels[2].setTo(new Scalar(0, 0, 0, 0));
//隻保留一個r通道
//合并rgb
// Core.merge(channels, mat);
//邊界填充
// Core.copyMakeBorder(mat, mat, top, bottom, left, right, Core.BORDER_REFLECT, new Scalar(255));
//定義一個新的mat 更每一個像素點相加
// Mat mat3 = new Mat(mat.size(), CvType.CV_8UC3,new Scalar(60,60,60,0));
//mat = mat+ mat3;
//畫一個矩形選框
Imgproc.rectangle(mat, new Point(10, 10), new Point(200, 200), new Scalar(255, 0, 0, 255), 5);
//設定目前mat.size縮放比例
//Imgproc.resize(mat, mat, new Size(0, 0), 2, 5);
//Debug.Log(mat.size());
Texture2D texture = new Texture2D(mat.cols(), mat.rows(), TextureFormat.RGBA32, false);
//texture.Apply()
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.line | 畫線 |
Imgproc.rectangle | 繪制一個簡單的矩形框,參考MatchTemplateExample |
Imgproc.circle | 用給定的中心和半徑繪制一個簡單的或實心的圓 |
Imgproc.minEnclosureCircle | 查找包含 2D 點集的最小面積的圓,該函數使用疊代算法找到二維點集的最小封閉圓 |
Imgproc.minEnclosureTriangle | 查找包圍二維點集的最小面積三角形并傳回其面積。該函數找到一個包圍給定二維點集的最小面積三角形并傳回其面積 |
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 | 高斯濾波 其它像素點離中心點像素點越近權重越大,效果比均指濾波好,參考 https://www.w3cschool.cn/opencv/opencv-a4gp2cfi.html |
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)
CV_8U - 8位無符号整數(0..255)
CV_8S - 8位有符号整數(-128..127)
CV_16U - 16位無符号整數(0..65535)
CV_16S - 16位有符号整數(-32768..32767)
CV_32S - 32位有符号整數(-2147483648..2147483647)
CV_32F - 32位浮點數(-FLT_MAX..FLT_MAX,INF,NAN)
CV_64F - 64位浮點數(-DBL_MAX..DBL_MAX,INF,NAN)
//CV_32FC1,CV_32FC2,CV_32FC3 分别是單通道 灰階圖,雙通道(RGB彩色圖像),三通道(rgb),四通道(rgba)
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 ();
//打開視訊檔案或捕獲裝置或 IP 視訊流以進行視訊捕獲。
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矩形結構元素構成
//核大小為3*3
Mat kerne= Mat.ones(30 ,30, CV_8U)
Imgproc.erode(src,dst,kerne,new Point(-1,-1),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();
//先計算dy 當dy為1時 當有色值為負的時候自動變為0為黑色,當dy=2時 ,是把負值轉為絕對值永遠為正
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;
}
//canny
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);
//canny
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;
}