C# 使用 OpenCV 基础

发布于:2025-05-24 ⋅ 阅读:(17) ⋅ 点赞:(0)

一、C#安装OpenCV

在这里插入图片描述
在这里插入图片描述安装上面三个模块

二、加载图片

  1. 导入
using OpenCvSharp;
  1. 加载图片
// 导入图片
Mat image = Cv2.ImRead(@"C:\x5.bmp");
// 拷贝
Mat image2 = image.Clone();

// 打开窗口
Cv2.NamedWindow("image", WindowFlags.AutoSize);
// 显示图片
Cv2.ImShow("image", image);

// 如果闪退写入下方代码
Cv2.WaitKey(0);

三、图片预处理

  1. 腐蚀
Mat dstimage = new Mat();
Cv2.NamedWindow("dstimage", WindowFlags.AutoSize);
// 腐蚀
Mat elem = Cv2.GetStructuringElement(MorphShapes.Cross, new Size() { Width = 10, Height = 10 });
Cv2.Erode(image, dstimage, elem);
Cv2.ImShow("dstimage", dstimage);
  1. 膨胀
Cv2.Dilate(image, dstimage, elem);
Cv2.ImShow("dstimage", dstimage);
  1. 开运算
Cv2.MorphologyEx(image, dstimage, MorphTypes.Close, elem);
Cv2.ImShow("dstimage", dstimage);
  1. 闭运算
Cv2.MorphologyEx(image, dstimage, MorphTypes.Open, elem);
Cv2.ImShow("dstimage", dstimage);
  1. 进行均值滤波处理
Cv2.NamedWindow("dstimage", WindowFlags.AutoSize);
Cv2.Blur(image, dstimage, new Size() { Width = 10, Height = 10 });
Cv2.ImShow("dstimage", dstimage);

四、保存图片

Cv2.ImWrite(@"C:\001.bmp", image);

五、关闭窗口释放资源

Cv2.DestroyAllWindows();

六、边缘化

  1. 处理x方向的梯度
Mat gart_x = new Mat();
Mat abs_gart_x = new Mat();
// 输入图片, 输出图片, 处理的格式 16位有符号, 1.0 x方向的处理倒数
Cv2.Sobel(image, gart_x, MatType.CV_165, 1, 0);
// 对图片进行高亮处理
Cv2.ConvertScaleAbs(gart_x, abs_gart_x);
Cv2.ImShow("x方向", abs_gart_x);
  1. 处理y方向
Mat gart_y = new Mat();
Mat abs_gart_y = new Mat();

Cv2.Sobel(image, gart_y, MatType.CV_165, 0, 1);
// 对图片进行高亮处理
Cv2.ConvertScaleAbs(gart_y, abs_gart_y);
Cv2.ImShow("x方向", abs_gart_y);
  1. 合并 x 和 y
Mat dst = new Mat();
// x的图像, x图像的权重, y的图像, y图像的权重
Cv2.AddWeighted(abs_gart_x, 0.5, abs_gart_y, 0.5, 0, dst);
Cv2.ImShow("合并", dst);

七、图片转换

  1. 灰度图
Mat grayImage = new Mat();
Cv2.CvtColor(image, grayImage, ColorConversionCodes.BGR2GRAY);
Cv2.ImShow("灰度图", grayImage);

八、调用摄像头进行录制

  1. 框架搭建
    在这里插入图片描述
  2. 完整代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
//using引入
using OpenCvSharp;
using OpenCvSharp.Extensions;
namespace 摄像头的录像与播放
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        //定义一个视频操作的类
        public VideoCapture cap = new VideoCapture();
        //定义一个储存视频的类
        public VideoWriter myAvi;

        //开关 用来控制摄像头的状态
        bool videoBool = false;

        private void button1_Click(object sender, EventArgs e)
        {
            //打开摄像头 
            cap.Open(0);
            if (!cap.IsOpened())
            {
                MessageBox.Show("摄像头打开失败");
                return;
            }
            //设置摄像头的采集参数   
            cap.Set(VideoCaptureProperties.FrameWidth,640);
            cap.Set(VideoCaptureProperties.FrameHeight,480);
            cap.Set(VideoCaptureProperties.Brightness,4);//亮度
            cap.Set(VideoCaptureProperties.Hue,5);//色调
            cap.Set(VideoCaptureProperties.Exposure,20);//曝光
            //定义一个图片   
            Mat image = new Mat();
            //定义一个窗口  
            Window window = new Window("capavi");
            int end = 0;
            while (end < 2)
            {
                if (cap.Read(image))//判断图片是否读取成功
                {
                    if (videoBool)//保存视频的开关
                    {
                        end = 1;
                        //录像本地保存
                        myAvi.Write(image);
                    }
                    else if (end == 1)
                    {
                        end = 2;
                        //释放资源
                        myAvi.Release();
                    }
                }
                //播放视频  
                window.ShowImage(image);//在打开的窗口显示图片
                //在picbox 显示  
                pictureBox1.Image = BitmapConverter.ToBitmap(image);
                Cv2.WaitKey(10);
            }

        }

        private void button2_Click(object sender, EventArgs e)
        {
            //开始录像的时候定义 录像的保存设置   
            //点开始录像储存录下来的视频   
            //路径名字,保存文件格式,帧率,分辨率,彩色图
            myAvi = new VideoWriter("a.avi",FourCC.MJPG,1,new OpenCvSharp.Size() { Width = 640,Height= 480},true);
            videoBool = true;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            videoBool = false;
        }
    }
}

九、拟合设计

1. 脚本绘制
//封装一个画圆的方法   
public static void DraeCircle(Mat image,Point center)
{
    //画圆  
    Cv2.Circle(image,center.X,center.Y,600/32,new Scalar(0,0,255),-1,LineTypes.Link8);
}

// 创建图片句柄
Mat atoImage= new Mat(600,600,MatType.CV_8UC3);
DraeCircle(atoImage,new Point(600/2,600/2));  // 调用方法
//显示   
Cv2.ImShow("atoImage", atoImage);
  1. 椭圆
//封装画椭圆的方法  
public static void DraeEillipes(Mat image,double angle)
{
    //绘制椭圆  
    Cv2.Ellipse(image,
                new Point(600/2,600/2),
                new Size(600/2,600/16),
                angle,0,360,
                new Scalar(255,129,0),
                2,LineTypes.Link8
            );
}

DraeEillipes(atoImage,90);
  1. 矩形
// 封装矩形
public static void DraeRectangle(Mat image, Rect box)
{
    Cv2.Rectangle(image, box, new Scalar(0, 0, 200), 2);
}

DraeRectangle(rookImage, new Rect(300, 300, 200, 200)); // (x, y, width, height)
  1. 线
//封装一个画线的方法  
public static void DraeLine(Mat image,Point start,Point end) {

    Cv2.Line(image,start.X,start.Y,end.X,end.Y,new Scalar(0,0,200),2,LineTypes.Link8);
}

DraeLine(rookImage,new Point(0,0),new Point(600,600));
2. 手动绘画

完整代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;
namespace _10绘制矩形
{
    internal class Program
    {
        //准备工作
        public static string window_name = "程序窗口";//窗口的名字
        public static Mat srcImage = new Mat(600,800,MatType.CV_8UC3,Scalar.All(0));//创建一张图片
        public static Rect g_rect;//矩形空的没赋值
        public static bool g_bDrbox = false;//是否开始绘制矩形 
        public static Random random = new Random(); 

        static void Main(string[] args)
        {
            //1.准备参数 
            g_rect = new Rect(-1,-1,0,0);
            Mat temImage = new Mat();
            //2.设置一个鼠标操作事件   
            Cv2.NamedWindow(window_name);//打开窗口窗口名字是 window_name
            //做一个委托 
            MouseCallback GetMouse = new MouseCallback(On_mous);
            //绑定事件到窗口上   
            Cv2.SetMouseCallback(window_name, GetMouse);
            //监听 
            while (true)
            {
                //赋值图像  
                srcImage.CopyTo(temImage);
                if (g_bDrbox)//判断是否开始绘制
                {
                    DrowRect(ref temImage, g_rect);
                }
                Cv2.ImShow(window_name, temImage);
                //结束循环  当用户按下  esc 键  
                if (Cv2.WaitKey(10) == 27)
                {
                    break;
                }
            }

        }
        //生成了一个委托函数 
        // @event  事件对象  , 里面包含了事件的一系列参数 , 比如鼠标按下的位置, 移动的位置 
        private static void On_mous(MouseEventTypes @event, int x, int y, MouseEventFlags flags, IntPtr userData)
        {
            //MouseEventTypes 委托类型  
            // MouseEventTypes.MouseMove;  鼠标移动
            //MouseEventTypes.LButtonDown;   鼠标按下
            //MouseEventTypes.LButtonUp;  鼠标抬起
            //移动 
            if (MouseEventTypes.MouseMove == @event)//判断鼠标有没有移动
            {
                if (g_bDrbox)//鼠标移动的时候是否是按下的
                {
                    g_rect.Width =  x - g_rect.X;
                    g_rect.Height = y - g_rect.Y;
                }
            }
            //按下 
            if (MouseEventTypes.LButtonDown == @event)//判断按下
            { 
                g_bDrbox = true;
                //记录鼠标按下的位置   
                g_rect = new Rect(x,y,0,0);//矩形的起使点
            }
           
            //松开
            if (MouseEventTypes.LButtonUp == @event)//判断松开
            {
                //松开的时候需要记录坐标  
                g_bDrbox = false;
                //判断坐标宽度小于零   
                if (g_rect.Width < 0)
                {
                    g_rect.X += g_rect.Width;
                    g_rect.Width *= -1;
                }
                if (g_rect.Height <0)
                {
                    g_rect.Y += g_rect.Height;
                    g_rect.Height *= -1;
                }
                //绘制图形
                DrowRect(ref srcImage, g_rect);
            }
          
        }
        //绘制图形的方法  
        public static void DrowRect(ref Mat image,Rect box)
        {
            //判断是否满足画矩形的条件
            if (box.BottomRight.X > box.TopLeft.X && box.BottomRight.Y > box.TopLeft.Y)
            {
                //画矩形  
                Cv2.Rectangle(image,box.TopLeft,box.BottomRight,new Scalar(random.Next(255), random.Next(255), random.Next(255)),2);

                //画圆  
                //Cv2.Circle(image, box.TopLeft.X, box.TopLeft.Y, Math.Abs(box.BottomRight.X - box.TopLeft.X), new Scalar(0, 0, 255), 1, LineTypes.Link8);
            }
        }
    }
}

十、图片缩放

  1. 方法1
// 缩小
Mat dst1 = new Mat();
Cv2.Resize(srcImage, dst1, new Size(srcImage.Cols / 2, srcImage.Rows / 2));
Cv2.ImShow("缩小", dst1);

// 放大
Mat dst2 = new Mat();
Cv2.Resize(srcImage, dst2, new Size(srcImage.Cols * 2, srcImage.Rows * 2));
Cv2.ImShow("放大", dst2);
  1. 方法1(推荐)
// 上采样放大但是上采样会尽量多的保留图像特征
Mat dst3 = new Mat();
// 通常是123倍
Cv2.PyrUp(srcImage, dst3, new Size(srcImage.Cols * 2, srcImage.Rows * 2));
Cv2.ImShow("上采样", dst3);

// 下采样缩小先要保存更多的特征
Mat dst4 = new Mat();
// 通常是1以下0.5,0.25
Cv2.PyrDown(srcImage, dst4, new Size(srcImage.Cols * 0.5, srcImage.Rows * 0.5));
Cv2.ImShow("下采样", dst4);

十一、加载视频

//加载视频定义视频变量  
VideoCapture cap = new VideoCapture(@"D:\lol.avi");
if (!cap.IsOpened())
{
    Console.WriteLine("视频加载失败");
    return;//打断程序下面的程序不在运行
}

//设置帧率  每秒播放的帧数  cap.Fps 获取视频帧率 进行计算 
int sleep = (int)Math.Round(1000 / cap.Fps);  
//创建一个视频播放窗口   
Window window = new Window();
//需要去提取视频中的每一帧 
Mat image = new Mat();
while (true)
{
    cap.Read(image);
    //判断一下 还有没有帧数 还有没有视频图像
    if (image.Empty())//判断当前的图片为空没有视频图片了
    {
        //停止读取   
        break;
    }
    //播放视频 
    //一 : window窗口播放  
    window.ShowImage(image);
    //二: 通过 opcv 来播放
    Cv2.ImShow("avi", image);
    Cv2.WaitKey(sleep);
}

十二、斑点查找

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;
namespace _斑点查找
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Mat imag = Cv2.ImRead(@"C:\blob.jpg");
            Cv2.ImShow("原图", imag);

            //创建一个斑点查找的对象  
            var deteParms = new SimpleBlobDetector.Params
            {
                FilterByColor = false,//不根据颜色查找
                FilterByArea = true,//开启面积赛选
                MinArea = 100,//最小面积
                MaxArea = 10000,//最大面积
                FilterByCircularity = false,//圆度不开启
                FilterByConvexity = false,//凹凸特征不开启
                FilterByInertia = false,//延展性不开启
            };
            //利用上面设置设置好的 参数进行斑点查找  
            SimpleBlobDetector dete = SimpleBlobDetector.Create(deteParms);
            //找到的参数接收一下  
            var KeyPoin = dete.Detect(imag);

            //绘制斑点 
            //用来储存绘制了斑点之后的图像
            Mat image_key = new Mat();
            //调用方法 把找到的斑点 给画出来  
            Cv2.DrawKeypoints(
                image:imag,
                keypoints: KeyPoin,
                outImage: image_key,
                color:Scalar.FromRgb(255,0,0),
                flags:DrawMatchesFlags.DrawRichKeypoints
                );
            Console.WriteLine($"斑点个数{KeyPoin.Length}");
            Cv2.ImShow("斑点", image_key);
            Cv2.WaitKey(0);
        }
    }
}

十三、点到多边形的距离

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;
namespace _点到多边形的距离
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Mat im = Cv2.ImRead(@"C:\lightning.png");
            Cv2.ImShow("原图",im);

            //进行二值化处理 
            Cv2.CvtColor(im,im,ColorConversionCodes.BGR2GRAY);//彩色图转换成灰度图
            //阈值处理
            Mat threshold = new Mat();//阈值处理过后的图片 
            //127,255 阈值的范围
            Cv2.Threshold(im,threshold,127,255,ThresholdTypes.Binary);
            Cv2.ImShow("二值化处理的图",threshold);

            //对处理完的图片进行轮廓检测
            //定义一个储存轮廓点的坐标 
            Point[][] countours = new Point[][] { };
            //储存轮廓乘次信息
            HierarchyIndex[] hier;
            //轮廓查找
            Cv2.FindContours(threshold,out countours,out hier,RetrievalModes.Tree,ContourApproximationModes.ApproxSimple,null);
            //Console.WriteLine($"轮廓数{countours.Length}");
            //把第一个轮廓拿出来  
            Point[] cnt = countours[0];

            //画一个圆  
            Point point = new Point(250,250);
            //画圆 
            Cv2.Circle(im,point,5,new Scalar(255,255,255),-1);
            Cv2.ImShow("画圆图片", im);

            //测量点到轮廓的距离  
            double dist = Cv2.PointPolygonTest(cnt,point,true);
            Console.WriteLine($"点到轮廓的距离{dist}");

            Cv2.WaitKey(0);
        }
    }
}

十四、基础轮廓查找

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;
namespace _基础轮廓查找
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Mat srcImage = Cv2.ImRead(@"C:\flowers.jpg", ImreadModes.Grayscale);
            Cv2.ImShow("原图",srcImage);

            //定义一个图片放处理过后的图 王里面画轮廓
            Mat dstImage = new Mat(srcImage.Size(),MatType.CV_8SC3);
            //像素值大于 190 的 设置为 255
            Cv2.Threshold(srcImage,srcImage,190,255,ThresholdTypes.Binary);
            Cv2.ImShow("处理完毕的图像", srcImage);

            //测量轮廓 需要两个 数组来储存数据  
            //定义二维数组储存坐标信息   
            Point[][] contours = new Point[][] { };
            //储存轮廓的信息
            HierarchyIndex[] hier;
            //输入图片,输出坐标信息,输出轮廓信息,输出的层次最外层,轮廓的检索模式,null
            Cv2.FindContours(srcImage,out contours,out hier,RetrievalModes.External,ContourApproximationModes.ApproxSimple,null);

            for (int i = 0; i < contours.Length;i++)
            {
                Console.WriteLine($"{i}");
                //绘制轮廓 
                Cv2.DrawContours(dstImage, contours,i,new Scalar(0,255,0),1,LineTypes.Link8, hier);
            }
            Cv2.ImShow("效果图",dstImage);
            Cv2.WaitKey(0);
        }
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到