OpenCV 图像复制和图像区域读写

图像复制

  • 共享数据, 使用 new Mat(srcMat, ...) 和 newMat=srcMat 生成新的Mat都和原Mat共享数据, 也就是说如果修改某一Mat,其他Mat也会随之改变
  • 复制全新的Mat, 使用CopyTo() 和 Clone() 方法将生成一个全新的Mat, 新Mat和原Mat不共享数据.

图像区域和点的读写

  • 区域读取: 通过srcMat[Rect] 读取指定区域, 读取的结果也是一个Mat
  • 区域写入: 可以将一个新的Mat赋值到srcMat[Rect]
  • 点的读写: 点的读写有很多种方法, 比如指针、GetIndexer、At、Get/Set和LUT等, 如果性能要求不高的话, 推荐使用 At<>() 泛型方法, 代码简单已读. 可参考 https://blog.csdn.net/TyroneKing/article/details/129108838
  • 点的读取: 可以通过 srcMat.At<>() 方法获取指定点的颜色值.
  • 点的写入: 可以直接给 srcMat.At<>()的结果赋值

图像共享数据的测试

    private void copyMats()
  {
      string pngFile = @"D:\my_workspace\opencv\images\draw.png";
      var mat = Cv2.ImRead(pngFile, ImreadModes.Color);

      //通过指定Rect方式截取图像,新的Mat和原Mat共享数据
      var partRef1 = new Mat(mat, new Rect(0, 0, mat.Width, mat.Height));

      //通过指定rowRange和colRange方式截图图像,新的Mat和原Mat共享数据
      var partRef2 = new Mat(mat, rowRange: new Range(50, 300), colRange: Range.All);

      //CopyTo()和Clone()都是复制出一份新的Mat
      var deepCopyMat = new Mat();
      mat.CopyTo(deepCopyMat);
      var cloneMat = mat.Clone();

      var rect = new Rect(10, 10, 100, 100);
      mat[rect] = new Mat(rect.Width, rect.Width, MatType.CV_8UC3, Scalar.Red);

      Cv2.ImShow("mat", mat);
      Cv2.ImShow("partRef1", partRef1);
      Cv2.ImShow("partRef2", partRef2);
      Cv2.ImShow("deepCopyMat", deepCopyMat);
      Cv2.ImShow("cloneMat", cloneMat);

      Cv2.WaitKey();
      Cv2.DestroyAllWindows();
  }

效果截图:

读写测试代码

    private void readWriteTest()
    {
        string pngFile = @"D:\my_workspace\opencv\images\draw.png";
        var srcMat = Cv2.ImRead(pngFile, ImreadModes.Color);

        var rect = new Rect(10, 10, 200, 200);

        //通过srcMat[Rect] 读取指定区域, 读取的结果也是一个Mat
        var newMat = srcMat[rect];

        //可以将一个新的Mat赋值到srcMat[Rect]
        srcMat[rect] = new Mat(rect.Width, rect.Width, MatType.CV_8UC3, Scalar.Green);

        for (int i = 0; i < srcMat.Rows; i++)
        {
            //可以通过 srcMat.At() 方法获取指定点的颜色值.
            var vec3b = srcMat.At<Vec3b>(i, 100);

            //可以直接给 srcMat.At()的结果赋值
            srcMat.At<Vec3b>(i, 100) = new Vec3b(vec3b.Item0, 0, 255);
        }

        Cv2.ImShow("mat", srcMat);
        Cv2.ImShow("newMat", newMat);

        Cv2.WaitKey();
        Cv2.DestroyAllWindows();
    }

效果截图:

参考:

posted @ 2023-11-05 19:47  harrychinese  阅读(92)  评论(0编辑  收藏  举报