0
votes

I have a 3 channel Mat image, type is CV_8UC3. I want to compare, in a loop, the intensity value of a pixel with its neighbours and then set 0 or 1 if the neighbour is greater or not. I can get the intensity calling Img.at<Vec3b>(x,y).

But my question is: how can I compare two Vec3b?

Should I compare pixels value for every channel (BGR or Vec3b[0], Vec3b[1] and Vec3b[2]), and then merge the three channels results into a single Mat object?

2
Yes you need to compare 3 channels seperately. - Sagar Patel
intensity is a single value (and so you matrix is single channel), not a BGR triplet. So, what do you want to compare? - Miki
I want to compare intensity represented by CV_8UC3. - Franktrt
So you want to compare the intensity of each channel separately? Maybe taking the max among the 3 channels? Or you want to define a comparison operation on Vec3b so you can compare them? It's really up to you, and what you need to do. If you clarify what's your final goal we can provide a clear answer. - Miki
Alternatively, you can perform census transform over all three channels of the RGB color space independently, and then concatenating the results together. The number of bits required to store census value will be three times more as in case of grayscale images. i.e in case of 3x3 census window the value would be 3*2^3 = 24 bits. - Kornel

2 Answers

0
votes

Me again :)

If you want to compare (greater or less) two RGB values you need to project the 3-dimensional RGB space onto a plane or axis.

Of course, there are many possibilities to do this, but an easy way would be to use the HSV color space. The hue (H), however, is not appropriate as a linear order function because it is circular (i.e. the value 1.0 is identical with 0.0, so you cannot decide if 0.5 > 0.0 or 0.5 < 0.0). However, the saturation (S) or the value (V) are appropriate projection functions for your purpose:

  • If you want to have colored pixels "larger" than monochrome pixels, you will prefer S.
  • If you want to have lighter pixels larger than darker pixels, you will probably prefer V.
  • Also any combination of S and V would be a valid projection function, e.g. S+V.
0
votes

As far as I understand, you want a measure to calculate distance/similarity between two Vec3b pixels. This can be reflected to the general problem of finding distance between two vectors in an n-mathematical space.

One of the famous measures (and I think this is what you're asking for), is the Euclidean distance.

If you are using Opencv then you can simply use:

cv::Vec3b a(1, 1, 1);
cv::Vec3b b(5, 5, 5);
double dist = cv::norm(a, b, CV_L2);

You can refer to this for reading about cv::norm and its options.

Edit: If you are doing this to measure color similarity, it's recommended to use the LAB color space as it's proved that Euclidean distance in LAB space is a good approximation for human perception of colors.

Edit 2: I see what you mean, for this you can get the magnitude of each vector and then compare them, something like this:

    double a_magnitude = cv::norm(a, CV_L2);
    double b_magnitude = cv::norm(b, CV_L2);
    if(a_magnitude > b_magnitude)
      // do something
    else
      // do something else.