OpenCV получает пиксели в определенном цветовом диапазоне - PullRequest
0 голосов
/ 01 декабря 2019

Я хочу получить пиксели в пределах определенного цветового диапазона в Android с помощью OpenCV.

Вот как я инициализирую imageReader (я использую RGBA):

    imageReader = ImageReader.newInstance(screenWidth, screenHeight, PixelFormat.RGBA_8888, 2);

Этокак я обрабатываю изображение из imageReader:

    Image image = reader.acquireLatestImage();

    //Create a Mat using 4 channels (since RGBA uses 4 channels) and fill it with the image-data.
    Mat rgba = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC4); 
    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
    byte[] bytes = new byte[buffer.remaining()];
    buffer.get(bytes);
    rgba.put(0, 0, bytes);

    //Range of colors to be detected:
    Scalar lower = new Scalar(10, 10, 100);
    Scalar upper = new Scalar(100, 100, 255);

    //Create a Mat using 3 channels (since HSV uses 3 channels)
    Mat hsv = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3);

    //Convert from source RGBA to destination HSV, the 3 specifes the channels for the destination Mat.
    Imgproc.cvtColor(rgba, hsv, Imgproc.COLOR_RGB2HSV, 3);

    //Do the filtering
    Core.inRange(hsv, lower, upper, hsv);

    //Convert back to RGBA (now i use 4 channels since the destination is RGBA)
    Imgproc.cvtColor(hsv, rgba, Imgproc.COLOR_HSV2RGB, 4); 

    image.close();           

Но при:

Imgproc.cvtColor(hsv, rgba, Imgproc.COLOR_HSV2RGB, 4); 

я получаю ошибку:

cv::Exception: OpenCV(4.1.2) ...

    > Invalid number of channels in input image:
    >     'VScn::contains(scn)'
    > where
    >     'scn' is 1

hsv используется каквходной аргумент в этой строке, но при преобразовании я всегда указывал, сколько каналов я использую, а для hsv я всегда использую три.

Почему я получаю эту ошибку?

1 Ответ

1 голос
/ 02 декабря 2019

После

//Do the filtering
Core.inRange(hsv, lower, upper, hsv);

матрица hsv имеет тип CV_8UC1 и представляет двоичную одноканальную маску, созданную функцией inRange.

Итак:

//Do the filtering
Mat mask = new Mat(hsv.rows(), hsv.cols(), CvType.CV_8U, new Scalar(0));
Core.inRange(hsv, lower, upper, mask);

// Set to (0,0,0) all pixels that are 0 in the mask, i.e. not in range
Core.bitwise_not( mask, mask);
hsv.setTo(new Scalar(0,0,0), mask);

//Convert back to RGBA (now i use 4 channels since the destination is RGBA)
Imgproc.cvtColor(hsv, rgba, Imgproc.COLOR_HSV2RGB, 4); 
...