0

I´m working with OpenCV and I have an image which has red, black and white colours. Specifically it's a QR code sourronded by a red square. What I wanna do is to dismiss the QR code and just keep the red square. This is what i've been trying to do:

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;

int main(){
    Mat imagen, imagenThreshold, imagenThreshold2;
    vector<Mat> canales;
    imagen = imread("qr.ppm");
    split(imagen,canales);
    imshow("RGB", canales[2]);
    return 0;

}

But after I run it, what I have left is the QR code WITHOUT the red square, exactly the opposite of what I want.

What am i doing wrong?

thanks

Saikat
  • 1,209
  • 3
  • 16
  • 30
mike
  • 15
  • 6
  • Have you tried imshow("RGB", canales[0]); or imshow("RGB", canales[1]); one of them might contain the image you need. – RedOctober May 04 '15 at 15:20
  • no, if i put those i get the full image all black and white – mike May 04 '15 at 15:21
  • This is a bit backwards and i'm sure there is a better way to do this but you can set canales[2] to zeros and then merge it back to the full image and you will have gotten rid of red square. – RedOctober May 04 '15 at 15:25
  • btw, sometimes imshow plays tricks on you. The image that you need might still be in canales[0] or canales[1] but it might be that background color is 0 and the foreground is 1 so when you display it with imshow it all looks black. But the information is there. Try conversting those images to CV32F and see if you get anything. – RedOctober May 04 '15 at 15:30
  • @RedOctober could you tell me how to do any of those ideas? – mike May 04 '15 at 15:33
  • canales[2] = Scalar(0); Mat newIm; merge(canales, newIm); – RedOctober May 04 '15 at 15:37
  • canales[2] = 0 doesn't work – mike May 04 '15 at 15:41
  • not working. a weird image appears: what used to be white is blue and what used to be red is black. black is black – mike May 04 '15 at 15:44
  • you can also try threshold(canales[0], newIm, 0.5, 255, THRESH_BINARY); imshow("win", newIm); – RedOctober May 04 '15 at 15:44
  • still doesn't work. my first result displays: what is red is now black. black is black and white is white – mike May 04 '15 at 15:48
  • well it sort of worked then. you zeroed out red channel so now your white color looks blue and you you convert your image to grayscale you get your nice and clean qr code – RedOctober May 04 '15 at 15:49
  • but i dont want the qr code! i want it to be gone. that's why the black (qr code) must go and the red (red square) must stay – mike May 04 '15 at 15:50

2 Answers2

1

You didn't post the image you were working on, so I generated a random test image. (Not a QR code, just random color blocks.) My answer relies on the fact that there are only 3 colors in the image: pure black, pure white, and pure red as defined below. Other colors or shades of these colors will require more processing.

On the left is my source image. In the middle is just the red channel of the source, the equivalent of your canales[2]. On the right is the red channel with all of the white blocks removed, our goal.

Source Image Source Red Channel Only Red

As you can see, the second image has white wherever the original image has red or white. That's because, as @prompt said in the other answer, pure white is made by setting all three channels to their maximum value.

Black = BGR(0, 0, 0)
Red = BGR(0, 0, 255)
White = BGR(255, 255, 255)

So we want only the pure red blocks. By knowing that we only have red and white (and no magenta or yellow or whatever) we can can take a shortcut and simply subtract the pixels that have blue in them (or green) from the red channel:

  imshow("RGB", canales[2] - canales[0]);

You can also take this red-only channel and merge it into a BGR image with all-zero blue and green channels to give you the output here, which I think makes even more clear that the white pixels have been removed:

Source Image Only Red

beaker
  • 16,331
  • 3
  • 32
  • 49
  • @mike Technically, it should be a `(red AND ~green) AND (red AND ~blue)` where `~` is the `NOT` operation, but in this case a simple subtraction works. – beaker May 08 '15 at 19:55
0

Probably you missunderstand what the function split exactly do.

It simply get your original image and then create three separated vector containing the specific values for each RGB channel.

Everything is white in the original image will be present in all the tree vectors. What is 100% red will be only in the 1st vector, what 100% green in the 2nd and what is 100% blue in the 3rd.

But what is white will be visible in all of them because as you probably know the white color is composed by a 0xFF of red, 0xFF of green and 0xFF of blue.

I suggest you to use the function inRange that do exactly what you need to do.

gugu69
  • 156
  • 7
  • could you tell me how to do it? i'm new at opencv – mike May 04 '15 at 15:46
  • I think you may find here very good sample of what you can do: http://stackoverflow.com/questions/9018906/detect-rgb-color-interval-with-opencv-and-c – gugu69 May 04 '15 at 16:07
  • that doesn't work for me because i have black in my image, so the result is everything black – mike May 04 '15 at 16:10
  • if the results is everything black is because your "red" is not a pure "red", in the sample use a filter strictly closed on the red components, from black to red. At this point the best would be if you could post your image so we can tell you exactly what values apply to the inRange function. – gugu69 May 05 '15 at 06:11