Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

opencv_core.inRange() not allowing opencv_core.Scalar as input type #684

Closed
wongjoel opened this issue Apr 26, 2017 · 5 comments
Closed

Comments

@wongjoel
Copy link

Environment

JavaCV version 1.3.2 (OpenCV version 3.2.0)

Problem

inRange(srcMat, new Scalar(H_MIN, S_MIN, V_MIN, 0), new Scalar(H_MAX, S_MAX, V_MAX, 0), destMat); will not compile because org.bytedeco.javacpp.opencv_core.inRange() only allows Mat for the lowerb and upperb parameters, instead of Mat or Scalar (i.e. InputArray).

Expected Behaviour

org.bytedeco.javacpp.opencv_core.inRange() should allow opencv_core.Scalar to be an input argument for lowerb and upperb. The documentation for inRange notes that upper and lower bounds can be either Mat or Scalar http://docs.opencv.org/3.2.0/d2/de8/group__core__array.html#ga48af0ab51e36436c5d04340e036ce981

Further reference

This functionality still works with the old API, so there is org.bytedeco.javacpp.opencv_core.cvInRangeS which takes CvScalar as boundaries and org.bytedeco.javacpp.opencv_core.cvInRange(); which takes CVMat as boundaries. Perhaps a similar solution could work here?

The Java bindings generated by OpenCV seem to able to handle this case, as seen in this sample code for Android in their repo https://github.com/opencv/opencv/blob/05b15943d6a42c99e5f921b7dbaa8323f3c042c6/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetector.java

The OpenCV header file in question seems to be core.hpp: https://github.com/opencv/opencv/blob/8ba95cd4985e739433e969cb56e682cfb24ced1a/modules/core/include/opencv2/core.hpp

@saudet
Copy link
Member

saudet commented Apr 26, 2017

inRange(srcMat, new Mat(H_MIN, S_MIN, V_MIN, 0), new Mat(H_MAX, S_MAX, V_MAX, 0), destMat);

should work though. The issue with cv::InputArray is that it's not possible to know from the header files if the function accepts cv::Scalar or std::vector<> or just Mat. As far as I know, all of them accept Mat, and if that's the case we might as well just use that. It works just as well. Do you need to use Scalar?

@wongjoel
Copy link
Author

wongjoel commented Apr 26, 2017

Thanks, I wasn't sure if Scalar was really just a special case of Mat. I won't need to use Scalar if a Mat is functionally equivalent. (Now I just need to write quick a test to convince myself that they are indeed equivalent.)

...Actually, I wrote up the following test case, and it failed, so perhaps there's still a problem?

Testcode

public static void main(String args[]){
	Mat image = imread("img.jpg");
	Mat hsv = new Mat();
	Mat filtered = new Mat();
	int H_MIN = 110;
	int H_MAX = 160;
	int S_MIN = 0;
	int S_MAX = 70;
	int V_MIN = 110;
	int V_MAX = 256;
	cvtColor(image, hsv, CV_BGR2HSV);
	inRange(hsv, new Mat(H_MIN, S_MIN, V_MIN, 0), new Mat(H_MAX, S_MAX, V_MAX, 0), filtered);
}

Error Message(s)

OpenCV Error: Sizes of input arguments do not match (The lower bounary is neither an array of the same size and same type as src, nor a scalar) in cv::inRange, file C:\projects\bytedeco\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-3.2.0\modules\core\src\arithm.cpp, line 1944
Exception in thread "main" java.lang.RuntimeException: C:\projects\bytedeco\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-3.2.0\modules\core\src\arithm.cpp:1944: error: (-209) The lower bounary is neither an array of the same size and same type as src, nor a scalar in function cv::inRange

@saudet
Copy link
Member

saudet commented Apr 26, 2017

I see, so new Mat(1, 1, CV_32SC4, new IntPointer(H_MIN, S_MIN, V_MIN, 0)) might work then...

@wongjoel
Copy link
Author

Yes that worked. Thanks! - that ends up being a pretty good workaround for this case, especially as that particular Mat constructor will take in a Scalar as an argument,

In summary, I ended up replacing my original call

inRange(srcMat, new Scalar(H_MIN, S_MIN, V_MIN, 0), new Scalar(H_MAX, S_MAX, V_MAX, 0), destMat);

with

`inRange(srcMat, new Mat(1, 1, CV_32SC4, new Scalar(H_MIN, S_MIN, V_MIN, 0)), new Mat(1, 1, CV_32SC4, new Scalar(H_MAX, S_MAX, V_MAX, 0)), destMat);

@saudet
Copy link
Member

saudet commented Jan 18, 2018

FYI, I've added new convenience constructors that are now part version 1.4. Enjoy!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants