天天看點

unity3d OpenCVForUnity(一)

插件文檔描述

簡單的矩形示例

unity3d OpenCVForUnity(一)
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)

unity3d OpenCVForUnity(一)
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

unity3d OpenCVForUnity(一)

門檻值 (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)
           

疊代圖對比

unity3d OpenCVForUnity(一)

邊緣檢測

簡單列舉兩個具體實作都差不多

梯度算子(Imgproc.Sobel)

unity3d OpenCVForUnity(一)

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;
    }
           
unity3d OpenCVForUnity(一)
unity3d OpenCVForUnity(一)