最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#使用OpenCvSharp實(shí)現(xiàn)圖像校正

 更新時(shí)間:2023年11月15日 09:53:48   作者:天天代碼碼天天  
這篇文章主要為大家詳細(xì)介紹了C#如何使用OpenCvSharp實(shí)現(xiàn)圖像校正功能,文中的示例代碼簡(jiǎn)潔易懂,具有一定的學(xué)習(xí)價(jià)值,需要的小伙伴可以參考下

效果

實(shí)現(xiàn)代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using OpenCvSharp;
using OpenCvSharp.Extensions;
 
namespace OpenCvSharp_圖像校正
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        string img = "test.png";
 
        private void Form1_Load(object sender, EventArgs e)
        {
            pictureBox1.Image = new Bitmap(img);
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            Mat src = new Mat(img);
 
            //轉(zhuǎn)化為灰度圖
            //Cv2.CvtColor(src, src, ColorConversionCodes.RGB2GRAY);
 
            InputArray kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3));
            Cv2.MorphologyEx(src, src, MorphTypes.Close, kernel, new OpenCvSharp.Point(-1, -1), 3);
            //Cv2.ImShow("MorphologyEx", src);
 
            /*
                ksize,高斯內(nèi)核大小,ksize.width和ksize.height必須是正奇數(shù),兩者可以不相同,值越大越模糊
                sigmaX,Y軸方向的標(biāo)準(zhǔn)差,值越大越模糊
                sigmaY,X軸方向的標(biāo)準(zhǔn)差,值越大越模糊
             */
            Cv2.GaussianBlur(src, src, new OpenCvSharp.Size(11, 11), 2, 2);
            //Cv2.ImShow("GaussianBlur", src);
 
            //Canny邊緣檢測(cè)
            Mat canny_Image = new Mat();
            Cv2.Canny(src, canny_Image, 10, 30, 3, false);
 
            OpenCvSharp.Point[][] contours;
            HierarchyIndex[] hierarchly;
            /*
	          findContours找到輪廓
	          第一個(gè)參數(shù):?jiǎn)瓮ǖ缊D像矩陣,可以是灰度圖,但更常用的是二值圖像,一般是經(jīng)過Canny、拉普拉斯等邊緣檢測(cè)算子處理過的二值圖像;
	          第二個(gè)參數(shù):contours 
	          第三個(gè)參數(shù):hierarchy
	          第四個(gè)參數(shù):輪廓的檢索模式
	  		        取值一:CV_RETR_EXTERNAL 只檢測(cè)最外圍輪廓,包含在外圍輪廓內(nèi)的內(nèi)圍輪廓被忽略
	  		        取值二:CV_RETR_LIST     檢測(cè)所有的輪廓,包括內(nèi)圍、外圍輪廓,但是檢測(cè)到的輪廓不建立等級(jí)關(guān)系,彼此之間獨(dú)立,沒有等級(jí)關(guān)系,這就意味著這個(gè)檢索模式下不存在父輪廓或內(nèi)嵌輪廓,所以hierarchy向量?jī)?nèi)所有元素的第3、第4個(gè)分量都會(huì)被置為-1,具體下文會(huì)講到
	  		        取值三:CV_RETR_CCOMP    檢測(cè)所有的輪廓,但所有輪廓只建立兩個(gè)等級(jí)關(guān)系,外圍為頂層,若外圍內(nèi)的內(nèi)圍輪廓還包含了其他的輪廓信息,則內(nèi)圍內(nèi)的所有輪廓均歸屬于頂層
	  		        取值四:CV_RETR_TREE     檢測(cè)所有輪廓,所有輪廓建立一個(gè)等級(jí)樹結(jié)構(gòu)。外層輪廓包含內(nèi)層輪廓,內(nèi)層輪廓還可以繼續(xù)包含內(nèi)嵌輪廓。
	          第五個(gè)參數(shù):輪廓的近似方法
	  		        取值一:CV_CHAIN_APPROX_NONE   保存物體邊界上所有連續(xù)的輪廓點(diǎn)到contours向量?jī)?nèi)
	  		        取值二:CV_CHAIN_APPROX_SIMPLE 僅保存輪廓的拐點(diǎn)信息,把所有輪廓拐點(diǎn)處的點(diǎn)保存入contours向量?jī)?nèi),拐點(diǎn)與拐點(diǎn)之間直線段上的信息點(diǎn)不予保留
	  		        取值三和四:CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
	          第六個(gè)參數(shù):Point偏移量,所有的輪廓信息相對(duì)于原始圖像對(duì)應(yīng)點(diǎn)的偏移量,相當(dāng)于在每一個(gè)檢測(cè)出的輪廓點(diǎn)上加上該偏移量,且Point可以是負(fù)值。不填為默認(rèn)不偏移Point()
	         */
            Cv2.FindContours(canny_Image, out contours, out hierarchly,
                RetrievalModes.External,
                ContourApproximationModes.ApproxSimple,
                new OpenCvSharp.Point(0, 0));
 
            if (contours.Length == 0)
            {
                MessageBox.Show("邊緣檢測(cè)失敗");
                return;
            }
 
            Random rnd = new Random();
            Scalar color;
            color = new Scalar(0, 255, 0);
            for (int i = 0; i < contours.Length; i++)
            {
                color = new Scalar(rnd.Next(0, 255), rnd.Next(0, 255), rnd.Next(0, 255));
                Cv2.DrawContours(src, contours, i, color, 2, LineTypes.Link4);
            }
            //Cv2.ImShow("contours", src);
 
            //求出面積最大的輪廓
            double max_area = 0.0;
            double currentArea = 0.0;
            OpenCvSharp.Point[] max_contour = null;
            for (int i = 0; i < contours.Length; i++)
            {
                currentArea = Cv2.ContourArea(contours[i]);
                if (currentArea > max_area)
                {
                    max_area = currentArea;
                    max_contour = contours[i];
                }
            }
 
            //多邊形擬合凸包的四個(gè)頂點(diǎn)
            OpenCvSharp.Point[] hull = Cv2.ConvexHull(max_contour);
            double epsilon = 0.02 * Cv2.ArcLength(max_contour, true);
            OpenCvSharp.Point[] approx = Cv2.ApproxPolyDP(hull, epsilon, true);
 
            if (approx.Length != 4)
            {
                MessageBox.Show("擬合凸包的四個(gè)頂點(diǎn)失敗");
                return;
            }
 
            Scalar scalar2 = new Scalar(0, 255, 255);
 
            Cv2.Line(src, approx[0], approx[1], scalar2, 1, LineTypes.Link4);
            Cv2.Line(src, approx[1], approx[2], scalar2, 1, LineTypes.Link4);
            Cv2.Line(src, approx[2], approx[3], scalar2, 1, LineTypes.Link4);
            Cv2.Line(src, approx[3], approx[0], scalar2, 1, LineTypes.Link4);
 
            //排序
            Array.Sort(approx, (cs1, cs2) =>
            {
                if (cs1 != null && cs1 != null)
                {
                    if (cs1.Y > cs2.Y)
                        return 1;
                    else if (cs1.Y == cs2.Y)
                    {
                        if (cs1.X < cs2.X)
                            return 1;
                        else return -1;
                    }
                    else
                        return -1;
                }
                return 0;
 
            });
 
            //算法找出的角點(diǎn)
            OpenCvSharp.Point2f[] srcPt = new OpenCvSharp.Point2f[4];
            srcPt[0] = approx[0];
            srcPt[1] = approx[1];
            srcPt[2] = approx[3];
            srcPt[3] = approx[2];
 
            //最小外接矩形
            RotatedRect rect = Cv2.MinAreaRect(srcPt);
            Rect box = rect.BoundingRect();
            OpenCvSharp.Point2f[] dstPt = new OpenCvSharp.Point2f[4];
 
            dstPt[0].X = box.X;
            dstPt[0].Y = box.Y;
 
            dstPt[1].X = box.X + box.Width;
            dstPt[1].Y = box.Y;
 
            dstPt[2].X = box.X + box.Width;
            dstPt[2].Y = box.Y + box.Height;
 
            dstPt[3].X = box.X;
            dstPt[3].Y = box.Y + box.Height;
 
            Mat src2 = new Mat(img);
            Mat final = new Mat();
            Mat warpmatrix = Cv2.GetPerspectiveTransform(srcPt, dstPt);//獲得變換矩陣
            Cv2.WarpPerspective(src2, final, warpmatrix, src.Size());//投射變換,將結(jié)果賦給final
 
            Bitmap temp = BitmapConverter.ToBitmap(final);
 
            pictureBox2.Image = temp;
 
            DrawLine(srcPt, dstPt);
 
            //Application.DoEvents();
            //System.Threading.Thread.Sleep(1000);
            //pictureBox2.Image = CutImage(temp, (int)p2f[0].X, (int)p2f[0].Y, (int)p2f[2].X, (int)p2f[2].Y);
 
        }
 
        void DrawLine(OpenCvSharp.Point2f[] srcPt, OpenCvSharp.Point2f[] dstPt)
        {
            Bitmap bmp = new Bitmap(img);
            Graphics g = Graphics.FromImage(bmp);
 
            Pen pen = new Pen(Color.Red, 3);
            Pen pen2 = new Pen(Color.Blue, 3);
 
            g.DrawLine(pen, srcPt[0].X, srcPt[0].Y, srcPt[1].X, srcPt[1].Y);
            g.DrawLine(pen, srcPt[1].X, srcPt[1].Y, srcPt[2].X, srcPt[2].Y);
            g.DrawLine(pen, srcPt[2].X, srcPt[2].Y, srcPt[3].X, srcPt[3].Y);
            g.DrawLine(pen, srcPt[3].X, srcPt[3].Y, srcPt[0].X, srcPt[0].Y);
 
            g.DrawLine(pen2, dstPt[0].X, dstPt[0].Y, dstPt[1].X, dstPt[1].Y);
            g.DrawLine(pen2, dstPt[1].X, dstPt[1].Y, dstPt[2].X, dstPt[2].Y);
            g.DrawLine(pen2, dstPt[2].X, dstPt[2].Y, dstPt[3].X, dstPt[3].Y);
            g.DrawLine(pen2, dstPt[3].X, dstPt[3].Y, dstPt[0].X, dstPt[0].Y);
 
            pictureBox1.Image = bmp;
 
        }
 
        /// <summary>
        /// 剪裁圖片
        /// </summary>
        /// <param name="src">原圖片</param>
        /// <param name="left">左坐標(biāo)</param>
        /// <param name="top">頂部坐標(biāo)</param>
        /// <param name="right">右坐標(biāo)</param>
        /// <param name="bottom">底部坐標(biāo)</param>
        /// <returns>剪裁后的圖片</returns>
        public Image CutImage(Image src, int left, int top, int right, int bottom)
        {
            Bitmap srcBitmap = new Bitmap(src);
            int width = right - left;
            int height = bottom - top;
            Bitmap destBitmap = new Bitmap(width, height);
            using (Graphics g = Graphics.FromImage(destBitmap))
            {
                g.Clear(Color.Transparent);
                //設(shè)置畫布的描繪質(zhì)量         
                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.DrawImage(srcBitmap, new Rectangle(0, 0, width, height), left, top, width, height, GraphicsUnit.Pixel);
            }
            return destBitmap;
        }
    }
}

以上就是C#使用OpenCvSharp實(shí)現(xiàn)圖像校正的詳細(xì)內(nèi)容,更多關(guān)于C# OpenCvSharp圖像校正的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#+EmguCV使用攝像頭讀取、保存視頻

    C#+EmguCV使用攝像頭讀取、保存視頻

    這篇文章主要為大家詳細(xì)介紹了C#+EmguCV使用攝像頭讀取、保存視頻,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • winform綁定快捷鍵的方法

    winform綁定快捷鍵的方法

    這篇文章主要介紹了winform綁定快捷鍵的方法,涉及WinForm設(shè)置窗體按鍵事件的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05
  • WinForm項(xiàng)目開發(fā)中Excel用法實(shí)例解析

    WinForm項(xiàng)目開發(fā)中Excel用法實(shí)例解析

    這篇文章主要介紹了WinForm項(xiàng)目開發(fā)中Excel用法,非常實(shí)用,需要的朋友可以參考下
    2014-08-08
  • C#中FileSystemWatcher的使用教程

    C#中FileSystemWatcher的使用教程

    這篇文章主要給大家介紹了關(guān)于C#中FileSystemWatcher使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 解決C# 截取當(dāng)前程序窗口指定位置截圖的實(shí)現(xiàn)方法

    解決C# 截取當(dāng)前程序窗口指定位置截圖的實(shí)現(xiàn)方法

    本篇文章是對(duì)C#中截取當(dāng)前程序窗口指定位置截圖的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • .NET實(shí)現(xiàn)父窗體關(guān)閉而不影響子窗體的方法

    .NET實(shí)現(xiàn)父窗體關(guān)閉而不影響子窗體的方法

    這篇文章主要介紹了.NET實(shí)現(xiàn)父窗體關(guān)閉而不影響子窗體的方法,很實(shí)用的功能,需要的朋友可以參考下
    2014-08-08
  • 基于C#編寫計(jì)算機(jī)選課程序

    基于C#編寫計(jì)算機(jī)選課程序

    在這篇文章中將介紹如何開發(fā)一個(gè)簡(jiǎn)單的計(jì)算機(jī)選課程序,文中主要使用了C#語(yǔ)言和Windows Forms來構(gòu)建這個(gè)應(yīng)用程序,感興趣的小伙伴可以了解下
    2024-10-10
  • C#編寫的Base64加密和解密類

    C#編寫的Base64加密和解密類

    本文給大家匯總介紹了幾種C#編寫的Base64加密和解密類的代碼,從簡(jiǎn)單到復(fù)雜,都能夠?qū)崿F(xiàn)功能,有需要的小伙伴根據(jù)自己的項(xiàng)目需求參考下吧。
    2015-05-05
  • C#中的DateTime是值類型還是引用類型

    C#中的DateTime是值類型還是引用類型

    近期遇到了DateTime到底是值類型還是引用類型的疑惑,順勢(shì)較深入地了解一下DateTime相關(guān)的內(nèi)容,大家有需要的朋友可以參考下
    2017-04-04
  • 關(guān)于System.Convert的那些事兒

    關(guān)于System.Convert的那些事兒

    本篇文章是對(duì)System.Convert的那些事兒,進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05

最新評(píng)論

铁岭县| 迁安市| 房产| 仁化县| 白银市| 镇宁| 鄂托克旗| 彭水| 麻阳| 柯坪县| 大理市| 集安市| 喀喇| 夏津县| 绥芬河市| 巴林左旗| 楚雄市| 纳雍县| 黄骅市| 鹤峰县| 鄂尔多斯市| 台北县| 新竹市| 张家口市| 弥勒县| 三台县| 岐山县| 轮台县| 竹北市| 金昌市| 静宁县| 翼城县| 仁化县| 长葛市| 襄城县| 芦溪县| 新宁县| 茂名市| 子洲县| 南宁市| 宿迁市|