shimat / opencvsharp

OpenCV wrapper for .NET
Apache License 2.0
5.39k stars 1.15k forks source link

Problems with the results of Mat.CopyTo() #1424

Closed yan97xh closed 1 year ago

yan97xh commented 2 years ago

Summary of your issue

i want to achieve the function that,i can use the mouse to draw any lines in picturebox ,and erase the lines. Here's my idea, when i need draw a line , i save the mouse location in the mousemove event of picturebox, and use the Cv2.Polylines() to draw it, the results is ok. when i need the erase , there're some issues. Here's how I did it to achieve erase . the src is intput Mat that need to be erased, the oriImg is the Initial image that without any manipulation. they are CV_8UC3.

  1. i also save the mouse location in the mousemove event of picturebox
  2. i creat a mask that has the same size and type as src.
  3. i use the Cv2.Polylines() to mask .
  4. finally, i use the oriImg.CopyTo(src, mask) It didn't turn out the way I wanted. the outputArray is more shallow than src, but the traces of the line can still be seen.

Environment

vs2019 opencvsharp4 4.5.5.20211231

Example code:

    class yLines
    {
        private int _thickness = 0;
        //是否是橡皮
        public bool IsEraser { set; get; }
        //点位数据
        public List<OpenCvSharp.Point> points = new List<Point>();

        public yLines(bool IsEraser = false)
        {
            this.IsEraser = IsEraser;
        }
        //画笔粗细
        public int thickness
        {
            set
            {
                _thickness = value;
                if (_thickness <= 0)
                    _thickness = 1;
            }
            get
            {
                return _thickness;
            }
        }

        //画笔颜色
        public OpenCvSharp.Scalar color { set; get; }
        //正常线
        public Mat DrawLines(Mat src)
        {
            List<List<OpenCvSharp.Point>> tempL = new List<List<OpenCvSharp.Point>>();
            tempL.Add(points);
            Cv2.Polylines(src, tempL, false, color, thickness);
            return src;
        }
        //橡皮 
        // 更新的图像为 src 最原始的图像为 oriImg 利用copyTo 将原始图像点位的像素覆盖到 src上实现橡皮擦
        public Mat DrawEraser(Mat src, Mat oriImg)
        {
            Mat mask = Mat.Zeros(src.Size(), MatType.CV_8UC3);
            if (src.Size() != oriImg.Size())
                return mask; 
            List<List<OpenCvSharp.Point>> tempL = new List<List<OpenCvSharp.Point>>();
            tempL.Add(points);
            //  mask只有线部分非0  其他都是0
            Cv2.Polylines(mask, tempL, false, color, thickness);  
            oriImg.CopyTo(src, mask);
            return src;  
        }
    }

Output:

图片

the traces of the line can still be seen. and i think the CopyTo() changes the color of only part of the channel

What did you intend to be?

how can i get the result that i want.

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.