0

I am using cv2::absdiff() for subtracting a scalar from an image Matrix. The code I am using is:

  double min;
  double max;
  Scalar mean;
  Scalar std_dev;

  minMaxLoc(img_a_color_planes[1], &min, &max);
  meanStdDev(img_a_color_planes[1], mean, std_dev);

  Mat img_a_color_planes[3];
  split(img_a, img_a_color_planes); 
  Mat oper = img_a_color_planes[1];

  absdiff(oper, mean, oper);
  divide(oper, std_dev, oper);
  multiply(oper, 10, oper);
  add(oper, mean, oper);

In here, I specifically copied the green channel of img_a into the Mat oper, inspite of output matrix oper being specified in absdiff. Even then, the green color channel img_a_color_planes[1] is being affected. I don't understand the reason for this. How can I avoid this? Here is how my img_a is getting affected after the absdiff operation:
Initial img_a :

enter image description here

After the absdiff operation:

enter image description here

Kapil Gupta
  • 7,091
  • 5
  • 16
  • 25

1 Answers1

2

The issue is that Mat oper = img_a_color_planes[1]; does not make a copy of the underlying array, just the header data. The same applies to the copy constructor.

You need to make an independent copy to avoid making changes to the original image. One way to do that is via the clone() method: Mat oper = img_a_color_planes[1].clone();. Cloning uses copyTo() under the hood: https://stackoverflow.com/a/15688165/2988730.

Quoting Mat docs:

Use a copy constructor or assignment operator where there can be an array or expression on the right side (see below). As noted in the introduction, the array assignment is an O(1) operation because it only copies the header and increases the reference counter. The Mat::clone() method can be used to get a full (deep) copy of the array when you need it.

Community
  • 1
  • 1
Mad Physicist
  • 107,652
  • 25
  • 181
  • 264