unity opencv Document Scanner

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using OpenCVForUnity;

public class Scanner : MonoBehaviour {
    public Texture2D baseTexture;
    public RawImage sourceRawImage;
    public RawImage targetRawImage;

	// Use this for initialization
	void Start () {
        Mat mainMat = new Mat(baseTexture.height, baseTexture.width, CvType.CV_8UC3);
        Mat grayMat = new Mat();

        //convert texture2d to matrix
        Utils.texture2DToMat(baseTexture, mainMat);
        //copy main matrix to grayMat
        mainMat.copyTo(grayMat);

        //convert color to gray
        Imgproc.cvtColor(grayMat, grayMat, Imgproc.COLOR_BGR2GRAY);
        //blur the image
        Imgproc.GaussianBlur(grayMat, grayMat, new Size(5, 5), 0);

        //thresholding make the image black and white
        Imgproc.threshold(grayMat, grayMat, 0, 255, Imgproc.THRESH_OTSU);
        //extract the edge of the image
        Imgproc.Canny(grayMat, grayMat, 50, 50);


        //prepare for the finding contours
        List<MatOfPoint> contours = new List<MatOfPoint>();
        //find the contour from canny edge image
        Imgproc.findContours(grayMat, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);


        List<MatOfPoint> tempTargets = new List<MatOfPoint>();
        for(int i=0; i<contours.Count; i++)
        {
            MatOfPoint cp = contours[i];
            MatOfPoint2f cn = new MatOfPoint2f(cp.toArray());
            double p = Imgproc.arcLength(cn, true);

            MatOfPoint2f approx = new MatOfPoint2f();
            //convert contour to readable polygon
            Imgproc.approxPolyDP(cn, approx, 0.03 * p, true);

            // find a contour with 4 points
            if (approx.toArray().Length == 4)
            {

                MatOfPoint approxPt = new MatOfPoint();
                approx.convertTo(approxPt, CvType.CV_32S);

                float maxCosine = 0;
                for (int j = 2; j < 5; j++)
                {
                    Vector2 v1 = new Vector2((float)(approx.toArray()[j % 4].x - approx.toArray()[j - 1].x), (float)(approx.toArray()[j % 4].y - approx.toArray()[j - 1].y));
                    Vector2 v2 = new Vector2((float)(approx.toArray()[j - 2].x - approx.toArray()[j - 1].x), (float)(approx.toArray()[j - 2].y - approx.toArray()[j - 1].y));

                    float angle = Mathf.Abs(Vector2.Angle(v1, v2));
                    maxCosine = Mathf.Max(maxCosine, angle);
                }

                if(maxCosine < 135f)
                {
                    tempTargets.Add(approxPt);
                }

            }

        }

        if(tempTargets.Count > 0)
        {
            //get the first contour
            MatOfPoint approxPt = tempTargets[0];
            //making source mat
            Mat srcPointsMat = Converters.vector_Point_to_Mat(approxPt.toList(), CvType.CV_32F);

            //making destination mat
            List<Point> dstPoints = new List<Point>();
            dstPoints.Add(new Point(0, 0));
            dstPoints.Add(new Point(0, 512));
            dstPoints.Add(new Point(512, 512));
            dstPoints.Add(new Point(512, 0));
            Mat dstPointsMat = Converters.vector_Point_to_Mat(dstPoints, CvType.CV_32F);

            //make perspective transform
            Mat M = Imgproc.getPerspectiveTransform(srcPointsMat, dstPointsMat);
            Mat warpedMat = new Mat(mainMat.size(), mainMat.type());
            //crop and warp the image
            Imgproc.warpPerspective(mainMat, warpedMat, M, new Size(512, 512), Imgproc.INTER_LINEAR);
            warpedMat.convertTo(warpedMat, CvType.CV_8UC3);



            //create a empty final texture
            Texture2D finalTexture = new Texture2D(warpedMat.width(), warpedMat.height(), TextureFormat.RGB24, false);
            //convert matrix to texture 2d
            Utils.matToTexture2D(warpedMat, finalTexture);

            targetRawImage.texture = finalTexture;

        }



	}
	
	// Update is called once per frame
	void Update () {
		
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值