5

I need to convert near white pixels to white and near black pixels to black.

I found a code snippet in python on how to do it.

hsv=cv.cvtColor(image,cv.COLOR_BGR2HSV)
# Define lower and upper limits of what we call "brown"
brown_lo=np.array([10,0,0])
brown_hi=np.array([20,255,255])
# Mask image to only select browns
mask=cv.inRange(hsv,brown_lo,brown_hi)
# Change image to red where we found brown
image[mask>0]=(0,0,255)

I have converted it java as below.

Mat temp= new Mat();
Imgproc.cvtColor(src,temp,COLOR_BGR2HSV);
Scalar low= new Scalar(10,0,0);
Scalar high= new Scalar(20,255,255);
Mat mask = new Mat();
inRange(temp,low,high,mask);

But I am facing problem converting below statement to java and there is no good opencv documentation in java with samples.

image[mask>0]=(0,0,255)

Could somebody help on how to convert above statement to java...?

I have tried setTo but it is not giving desired behaviour(attached screenshot below). Refer https://stackoverflow.com/a/50215020/12643143 for the expected result.

src.setTo(new Scalar(0,0,255),mask);

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
RAMU
  • 176
  • 1
  • 8

2 Answers2

1

I recommend to use setTo(). This method can set all he pixels in a Mat. If an optionally mask argument is specified, then all the pixels who have a corresponding pixel with a non-zero value in the mask will be set.

Thus the python statement

image[mask>0]=(0,0,255)

can be substituted in Java by:

image.setTo(new Scalar(0, 0, 255), mask);

where image has to be a Mat object.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
1

Answer to the question

As @Rabbid76 mentioned setTo is the correct way to do this. However if you want specific logic like image[mask>127]=(0,0,255), then do threshold (Imgproc.threshold(grey,grey, 127, 255, THRESH_BINARY);) and then use setTo.

Solution to my problem

Actually my problem was not due to setTo. Its the logic mismatch between how I read/write the Mat in my code Vs the post I referred.

I am posting the solution to the problem that I have faced so that it might help new bees like me.

Problem in reading Image

The post use Imgcodecs.imread() to read image to Mat in BGR format.

Whereas I am loading bitmap using bitmapToMat in CV_8UC4 type as below which reads the image to Mat in RGBA format.

Mat src = new Mat(bitmap.getHeight(), bitmap.getWidth(), CV_8UC4);
org.opencv.android.Utils.bitmapToMat(bitmap, src);

Fix is to convert the format properly.

Mat src = new Mat(bitmap.getHeight(), bitmap.getWidth(), CV_8UC3); //notice 3 channel
org.opencv.android.Utils.bitmapToMat(bitmap, src);
Imgproc.cvtColor(src,hsv,COLOR_RGB2HSV); //Convert RGB to HSV. COLOR_RGBA2HSV not exist, hence we load it in CV_8UC3(3 channel R,G,B).

Problem in writing the Image

Similarly as we have differences in reading between bitmapToMat and imread, the same are applicable for writing. Imgcodecs.imwrite() will write the BGR image to bitmap, where as I have to convert it back to RGB format for matToBitmap to work like Imgproc.cvtColor(rgb, rgb, Imgproc.COLOR_BGR2RGB);

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
RAMU
  • 176
  • 1
  • 8