OpenCV

本文介绍了使用OpenCV进行图像处理,包括读取和显示图片、找轮廓、K-means聚类分析,然后实现背景与人物二值化,并使用随机颜色混合边缘效果。展示了如何利用OpenCV进行人物分离和背景替换的技术过程。
摘要由CSDN通过智能技术生成

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
 
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using OpenCvSharp;

namespace OpenCVTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            T1();
        }

        private void T1()
        {
            Mat dst = new Mat();
            Mat src = Cv2.ImRead("C:\\Pictures\\a.jpg", ImreadModes.Color);
            Mat dst_Image = MyFindContours(src);
            Cv2.ImShow("srcImage:", src);
            Cv2.ImShow("contours", dst_Image);

            Mat data = mat_to_samples(src);

            int numCluster = 4;
            Mat labels = new Mat();
            var centers = new Mat();
            TermCriteria criteria = new TermCriteria(CriteriaTypes.Eps, 10, 0.1);   // TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 0.1);
                                                                                    // kmeans(data, numCluster, labels, criteria, 3, KMEANS_PP_CENTERS);
            Cv2.Kmeans(data, numCluster, labels, criteria, 3, KMeansFlags.PpCenters, centers);
            //https://github.com/VahidN/OpenCVSharp-Samples/blob/master/OpenCVSharpSample11/Program.cs

            // 3.背景与人物二值化
            Mat mask = Mat.Zeros(src.Size(), MatType.CV_8UC1);
            int index = src.Rows * 2 + 2;  //获取点(2,2)作为背景色
            int cindex = labels.At<int>(index, 0);
            src.CopyTo(dst);

            /*  提取背景特征 */
            for (int row = 0; row < src.Rows; row++)
            {
                for (int col = 0; col < src.Cols; col++)
                {
                    index = row * src.Cols + col;
                    int label = labels.At<int>(index, 0);
                    if (label == cindex)
                    { // 背景
                        mask.At<byte>(row, col) = 0;
                    }
                    else
                    {
                        mask.At<byte>(row, col) = 255;
                    }
                }
            }


            Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3), new Point(-1, -1));
            Cv2.Erode(mask, mask, kernel);
            Cv2.GaussianBlur(mask, mask, new Size(3, 3), 0, 0);

            RNG rng = new RNG();
            Vec3b color = new Vec3b();
            color[0] = (byte)rng.Uniform(0, 255);
            color[2] = (byte)rng.Uniform(0, 255);
            color[1] = (byte)rng.Uniform(0, 255);
            dst = Mat.Zeros(src.Size(), src.Type());

            for (int row = 0; row < src.Rows; row++)
            {
                for (int col = 0; col < src.Cols; col++)
                {
                    int temp = mask.At<byte>(row, col);//(row,col)的像素值
                    if (temp == 255)//在mask为白色的区域,将src直接赋给dst
                    {
                        dst.At<Vec3b>(row, col) = src.At<Vec3b>(row, col);//前景
                    }
                    else if (temp == 0) //在mask为黑色的区域,给dst添上随机颜色

                    {
                        dst.At<Vec3b>(row, col) = color; //背景
                    }

                    else//边缘处:非纯黑/非纯白
                    {
                        double weight = temp / 255;//权重值(可以理解为灰度占比)
                                                   //在(row,col)上src的rgb值
                        int b_src = src.At<Vec3b>(row, col)[0];
                        int g_src = src.At<Vec3b>(row, col)[1];
                        int r_src = src.At<Vec3b>(row, col)[2];
                        //在(row,col)上color的rgb随机值
                        int b_color = color[0];
                        int g_color = color[1];
                        int r_color = color[2];

                        //按权重weight通道混合
                        dst.At<Vec3b>(row, col)[0] = (byte)(weight * b_src + (1 - weight) * b_color);
                        dst.At<Vec3b>(row, col)[1] = (byte)(weight * g_src + (1 - weight) * g_color);
                        dst.At<Vec3b>(row, col)[2] = (byte)(weight * r_src + (1 - weight) * r_color);
                    }
                }


                Cv2.ImShow("mask", mask);
                using (new Window("dst image", dst))
                {
                    Cv2.WaitKey();
                }
            }

        }

        Mat mat_to_samples(Mat image)
        {
            int width = image.Cols;
            int height = image.Rows;
            int samplecount = width * height;//采样数 
            int dims = image.Channels();
            Mat temp = new Mat(samplecount, dims, MatType.CV_32FC1, new Scalar(10));// (samplecount, dims, CV_32F, Scalar(10));//存放样本点

            // RGB 数据转换到样本数据
            int index = 0;
            for (int row = 0; row < height; row++)
            {
                for (int col = 0; col < width; col++)
                {
                    index = row * width + col;//索引值 = 行*宽度 + 列
                    Vec3b bgr = image.At<Vec3b>(row, col);
                    temp.At<float>(index, 0) = Convert.ToInt32(bgr[0]);
                    temp.At<float>(index, 1) = Convert.ToInt32(bgr[1]);
                    temp.At<float>(index, 2) = Convert.ToInt32(bgr[2]);
                }
            }

            return temp;
        }


        // findContours()用于对物体轮廓进行检测
        Mat MyFindContours(Mat srcImage)
        {
            //转化为灰度图
            Mat src_gray = new Mat();
            Cv2.CvtColor(srcImage, src_gray, ColorConversionCodes.RGB2GRAY);

            //滤波
            Cv2.Blur(src_gray, src_gray, new Size(3, 3));

            //Canny边缘检测
            Mat canny_Image = new Mat();
            Cv2.Canny(src_gray, canny_Image, 100, 200);

            //获得轮廓
            Point[][] contours;
            HierarchyIndex[] hierarchly;
            Cv2.FindContours(canny_Image, out contours, out hierarchly, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple, new Point(0, 0));

            //将结果画出并返回结果
            Mat dst_Image = Mat.Zeros(canny_Image.Size(), srcImage.Type());
            Random rnd = new Random();
            for (int i = 0; i < contours.Length; i++)
            {
                Scalar color = new Scalar(rnd.Next(0, 255), rnd.Next(0, 255), rnd.Next(0, 255));
                Cv2.DrawContours(dst_Image, contours, i, color, 2, LineTypes.Link8, hierarchly);
            }
            return dst_Image;
        }

        void Test1()
        {
            Mat src = new Mat("C:\\Pictures\\a.jpg", ImreadModes.Grayscale);
            // Mat src = Cv2.ImRead("lenna.png", ImreadModes.GrayScale);
            Mat dst = new Mat();

            Cv2.Canny(src, dst, 50, 200);
            using (new Window("src image", src))
            using (new Window("dst image", dst))
            {
                Cv2.WaitKey();
            }
        }

    }
}
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Farmwang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值