I have learned OpenCV for C++/Python
, and I'm learning OpenCV for Java
these days, and find this question is a good practice for pixel loop
.
I'm use OpenCV 4.0.0-pre
, so some functions maybe in other modules/packages/headers
...
As @Dan Mašek Suggests, you should convert the image using COLOR_BGR2HSV
. Except this, I also find that you have wrote the wrong hsv ranges.
For this code in C++:
inRange(hsv, Scalar(0, 70, 50), Scalar(10, 255, 255), mask1);
inRange(hsv, Scalar(170, 70, 50), Scalar(180, 255, 255), mask2);
Mat1b mask = mask1 | mask2;
Your range condition in Java:
(( 0.0>=H && H<=10.0) && (70.0>=S && S<=255.0) && (50.0>=V && V<=255.0)) ||
(( 170.0>=H && H<=180.0) && (70.0>=S && S<=255.0) && (50.0>=V && V<=255.0))
It should be:
(( 0.0<=H && H<=10.0) && (70.0<=S && S<=255.0) && (50.0<=V && V<=255.0)) ||
(( 170.0<=H && H<=180.0) && (70.0<=S && S<=255.0) && (50.0<=V && V<=255.0))
Or this:
///!(1) Create mask by loop with condition
(( 0.0<=H && H<=10.0) || ( 170.0<=H && H<=180.0)) && (70.0<=S && S<=255.0) && (50.0<=V && V<=255.0)
Or this:
///!(2) Create mask by calling API
Mat mask1 = new Mat();
Mat mask2 = new Mat();
Core.inRange(hsv, new Scalar(0, 70, 50), new Scalar(10, 255, 255), mask1);
Core.inRange(hsv, new Scalar(170, 70, 50), new Scalar(180, 255, 255), mask2);
Mat mask= new Mat();
Core.bitwise_or(mask1, mask2, mask);
In Java:
//! 2018.05.08 18:50:59 CST
//! 2018.05.08 20:53:48 CST
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.core.*;
import java.util.*;
public class test
{
public static void main(String[] args)
{
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat img = Imgcodecs.imread("test.jpg", Imgcodecs.CV_LOAD_IMAGE_COLOR);
if ((img == null) || img.empty()) {
System.out.println("Failed to load input img.");
System.exit(-1);
}
Mat hsv = new Mat();
Imgproc.cvtColor(img, hsv, Imgproc.COLOR_BGR2HSV);
///! (1) Create the mask by loop
Mat mask = new Mat(hsv.size(), CvType.CV_8UC1, new Scalar(0,0,0));
for(int i=0;i<hsv.rows();++i){
for(int j=0;j<hsv.cols();++j){
double[] data = hsv.get(i,j);
double H = data[0];
double S = data[1];
double V = data[2];
//mask[np.where(((h<10) | ((h>=170) & (h<=180)) ) & ((s>=70) & (s<=255)) & ((v>=50) & (v<=255)) )] = 255
if((( 0.0<=H && H<=10.0) || ( 170.0<=H && H<=180.0)) && (70.0<=S && S<=255.0) && (50.0<=V && V<=255.0)) {
mask.put(i,j, 255);
}
}
}
///!(2) Create mask by calling API
Mat mask1 = new Mat();
Mat mask2 = new Mat();
Core.inRange(hsv, new Scalar(0, 70, 50), new Scalar(10, 255, 255), mask1);
Core.inRange(hsv, new Scalar(170, 70, 50), new Scalar(180, 255, 255), mask2);
Mat mask_combined = new Mat();
Core.bitwise_or(mask1, mask2, mask_combined);
///! Get the masked
Mat masked = new Mat();
Core.bitwise_and(img, img, masked, mask);
//Core.bitwise_and(img, img, masked, mask_combined);
Imgcodecs.imwrite("test_mask.jpg", mask);
Imgcodecs.imwrite("test_masked.jpg", masked);
}
}
In Python, it can be wrote as:
import cv2
import numpy as np
img = cv2.imread("test.jpg")
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h,s,v = cv2.split(hsv)
## (1) by hand
mask = np.zeros_like(s)
mask[np.where(((h<10) | ((h>=170) & (h<=180)) ) & ((s>=70) & (s<=255)) & ((v>=50) & (v<=255)) )] = 255
## (2) call api
mask1 = cv2.inRange(hsv, (0, 70, 50), (10, 255, 255))
mask2 = cv2.inRange(hsv, (170, 70, 50), (180, 255, 255))
mask = cv2.bitwise_or(mask1, mask2)
masked = cv2.bitwise_and(img, img, mask=mask)
Here is my result:
