Ask Your Question

OpenCV CUDA - method that works like inRange()

asked 2016-04-01 02:41:46 -0500

Graver gravatar image

updated 2016-04-01 03:03:01 -0500

berak gravatar image

I have a image in BGR color space and I convert it in HSV color space. I want to find a method that works on GPU like inRange works on CPU to binarize my image and obtain a threshold. Afer the conversion in HSV colorspace I make a split in three channels. After that I apply threshold() on every channel and finaly call function merge().

The problem is that in the last step i don't get the binary image. The image is colored.

Here is my code

gpu::cvtColor(myFrame_device, myFrameHSV_device, COLOR_BGR2HSV);
gpu::GpuMat channels_device[3];
gpu::GpuMat channels_device_dest[3];
gpu::split(myFrameHSV_device, channels_device);
//Mat myFrameEqualizedHSV(myFrameHSV_device);
//threshold HSV
gpu::threshold(channels_device[0], channels_device_dest[0], 0, 225, THRESH_BINARY);
gpu::threshold(channels_device[1], channels_device_dest[1], 75, 225, THRESH_BINARY);
gpu::threshold(channels_device[2], channels_device_dest[2], 0, 225, THRESH_BINARY);
gpu::merge(channels_device_dest,3, threshold_device);
edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted

answered 2016-04-01 03:06:28 -0500

That is normal: merge creates a multi-channels image from multiple images. (see the doc here). The inRange function creates a binary mask, and I assume, according to your title, that is what you want to do. The inRange function does not exist (yet) in GPU, therefore, you have two options:

  1. Implement the GPU version of inRange (make a pull request and make the OpenCV community happy). Here is some info if you want to contribute to OpenCV.
  2. Download the merged image and to the inRange on CPU, eventually upload the result to GPU if you still need to process the image after that. This option is not suitable if you have to do some other process to the GPU after, as it could be slower than doing everything on CPU.
edit flag offensive delete link more



I need only to detect some squares in a image. The squares are found with canny(). The problem is that i need to binarize a HSV image. I tried to make the sum of the channels but now i have some gray in image.

Graver gravatar imageGraver ( 2016-04-01 04:01:51 -0500 )edit

Hi ! I am currently working on the same thing as described above and could'nt really figure out what to do exactly , hence faced similiar issues. I just wanted to ask if anybody could finally get a proper working implentation of it or not as I need it for my project work too. Graver, were you able to do it? Please let me know , yes or no. Thanks!

sarthakahuja11 gravatar imagesarthakahuja11 ( 2016-09-29 14:17:10 -0500 )edit

answered 2017-08-20 23:10:05 -0500

As mentioned before "merge creates a multi-channels image ". The right approach would be using gpu::bitwise_and() function twice on the three threshold channels to get a binary single channel. I faced the same problem and came across your post and I assume many will face the same problem since there is no gpu::inrange() function. Here is the code I have implemented.

gpu::GpuMat imgpu;
gpu::GpuMat hsv;
gpu::GpuMat shsv[3];
gpu::GpuMat thresc[3];
gpu::GpuMat temp;
gpu::GpuMat thres;

//Transform image to HSV
gpu::cvtColor(imggpu, hsv, COLOR_BGR2HSV);

//Split HSV 3 channels
gpu::split(hsv, shsv);

//Threshold HSV channels
gpu::threshold(shsv[0], thresc[0], 45, 90, THRESH_BINARY);
gpu::threshold(shsv[1], thresc[1], 100, 225, THRESH_BINARY);
gpu::threshold(shsv[2], thresc[2], 20, 225, THRESH_BINARY);

//Bitwise AND the channels
gpu::bitwise_and(thresc[0], thresc[1],temp);
gpu::bitwise_and(temp, thresc[2], thres);
edit flag offensive delete link more
Login/Signup to Answer

Question Tools

1 follower


Asked: 2016-04-01 02:41:46 -0500

Seen: 1,362 times

Last updated: Apr 01 '16