1
votes

I am trying to make a simple program that reads the pixel values (BGR) of an input image and makes an output image of the same size but if the pixel in the original picture is white, the output image's pixel (of the same position) is Blue, and if the pixel is not white, makes the same pixel in the output image Black. However I'm having difficulties getting it to work correctly. It seemed pretty easy but it doesn't behave how I'd expect it to. Here's my code for it below:

Mat input;
Mat output;
Vec3b color;
input = imread("C:/temp/COLORTEST2.png", CV_LOAD_IMAGE_UNCHANGED);
output = input;
int rows = input.rows;
int cols = input.cols;
int Blue, Green, Red;
cout << "Rows: " << rows << "\nColumns: " << cols << "\nTotal Pixels: " << (rows*cols) << endl;
cout << "Calculating...\n\n";
for (j = 0; j < rows; j++)
{
    for (i = 0; i < cols; i++)
    {
        color = input.at<Vec3b>(Point(j, i));
        Blue = color.val[0];
        Green = color.val[1];
        Red = color.val[2];

        if (Blue == 255 && Green == 255 && Red == 255){
            W++; //White count +1
            output.at<Vec3b>(Point(j, i))[0] = 255;
            output.at<Vec3b>(Point(j, i))[1] = 0;
            output.at<Vec3b>(Point(j, i))[2] = 0;
        }
        else{
            NW++; //NonWhite count +1
            output.at<Vec3b>(Point(j, i))[0] = 0;
            output.at<Vec3b>(Point(j, i))[1] = 0;
            output.at<Vec3b>(Point(j, i))[2] = 0;
            //cin >> response;
        }

    }
}
cout << "White Pixels: " << W << "\nNon-White Pixels: " << NW << endl;
imwrite("C:/temp/Output.png", output);
waitKey();

Like I said, seems simple enough, but it crashes when I run it. If i switch rows and cols in the for loops it runs fine but the output image looks nothing like it should (vertical strips with a few black pixels). The function "mat.at(Point(j, i))" seems to be the problem, looks like it crashes at a certain point, as if its looking for a point that doesn't exist almost as if the rows and columns were switched but that doesn't make sense... I've also tested it by making an MS paint picture (20 x 30) and putting a single black pixel at 1x1 and it said that at 1x1 its BGR was 255, 0, 0... which means it thought it was blue and makes even less sense... I am really stumped and if anyone has any advice on this funtion and how it works I'd be very thankful.

EDIT: Here is the output and input images. This is the error i was talking about, the output is stripped and not even completed: http://imgur.com/a/DPRlO Specs:
Windows 8.1
Visual Studio 2013
OpenCV 2.4.10
C++

2
Please share the error message,, the line it crashes.. any information that helps to identify the problem quicklyHumam Helfawi

2 Answers

0
votes

I tested your code with the sample input image that you provided.Your input image contains alpha channel.So it is a four channel image.you should use Vec4b instead of Vec3b to get correct result. Otherwise change the statement input = imread(imgpath, CV_LOAD_IMAGE_UNCHANGED) to input = imread(imgpath, CV_LOAD_IMAGE_COLOR) to load image in 3 channel BGR format and to continue with Vec3b.

0
votes
output = input;

This is a shallow copy. That means every time you change output data, the data of input will be changed. You should do it like this:

output = input.clone();

Point(x,y) => x refers to column and y refers to rows. You are doing it reversely.

Change those:

for (j = 0; j < rows; j++)
{
    for (i = 0; i < cols; i++)
    {

to those:

for (j = 0; j < cols; j++)
{
    for (i = 0; i < rows; i++)
    {

BTW BLUE,RED,GREEN should be uchar rather than int.