Javacv: opencv_core.inRange() not allowing opencv_core.Scalar as input type

Created on 26 Apr 2017  路  5Comments  路  Source: bytedeco/javacv

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

Most helpful comment

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);

All 5 comments

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?

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

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

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);

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

y4nnick picture y4nnick  路  3Comments

The-Crocop picture The-Crocop  路  5Comments

newstarbka picture newstarbka  路  5Comments

kongqw picture kongqw  路  4Comments

ahmedaomda picture ahmedaomda  路  4Comments