Ondrej
Ondrej

Reputation: 15

scale pixels of an image using opencv library and c++

I'm trying to create simple 1D Barcode Reader using OpenCV 2.4.5 and Visual Studio 2010 Express.

Here is my code so far:

//define Image path:
char* imageName = "D:\\Barcode Reader\\test3.jpg";
cv::Mat src = cv::imread(imageName);

if( !src.data )
{ return -1; }

//convert image to grayscale img:    
cv::Mat gray_image;
cvtColor (src, gray_image, CV_BGR2GRAY);

unsigned char color;
unsigned char next_black_color = 0;
unsigned char next_white_color = 0;
int buffer[500];

float factor = (float)gray_image.cols / (float)required_width;

//start to search for pixels from left to right (in the middle of the img):
unsigned char *position  = gray_image.ptr(gray_image.rows/2,0);

//iterate through the whole image length:
for (int col = 1; col <= gray_image.cols; col++)
{   
//...and store the pixel value in color variable for possible output (which would be like 0-127 for black colors and 127-255 for white colors:
    color = *position;
    position++;
//check the pixel value ( < 127 everything bellow has dark color):
    if (color < 127)
{
//...and after each position checked, go to next pixel and save the number of occurences of black pixels:

        next_black_color++;
        buffer[col] = next_black_color;
        std::cout << col << ": " << buffer[col] << " ";
}
else
{
//set the counter variable to null for the next occurence of black pixel:
        next_black_color = 0;
}
//the same goes for white pixels:
    if (color > 127)
{   
    next_white_color++;
    buffer[col] = next_white_color;
    std::cout << col << ": " << buffer[col] << " ";
}
else
{
    next_white_color = 0;
}
}

//show the results:
std::cout<<" Number of pixels in width = " << src.cols << std::endl <<
"Number of pixels in height = " << src.rows << std::endl;

cv::imshow("Normal Image", src);
cv::imshow("Gray Image", gray_image);

cv::waitKey(0);

return 0;

The Test Image is 100x100px Image with black and white pixels in following order (described as binary code for better understanding: 1=black,0=white) 10100<..white pixels..>00101

The reason I'm making this is simple...

Let's say I have an UPC Barcode which can be 81 pixels long. However, my loaded Image is over 1000 pixels in length.

To apply the detection and to compare my loaded image with the UPC pattern I have to scale the loaded image to correct pixel value first. ( I use the word "scale" ...because if I would just "resize" my image... it would cut off 919 pixels, making the detection impossible.)


I'm facing the following problem using this implementation:

The occurences will be stored as following:

____[Array]____
Position | Occurence
1 ......... 1 (First position with first black pixel)
2 ......... 1 (white)
3 ......... 1 (black)
4 ......... 1 (white pixels until next black pixel appears..)
5 ......... 2 (___Problem here!___ ... should be 94!)
6 ......... 3          .
. ......... .          .
100 ....... 100(end)

But it should be:

____[Array]____
Position | Occurence
1 ......... 1  (First position with first black pixel)
2 ......... 1  (white)
3 ......... 1  (black)
4 ......... 94 (count all white pixels until black appears again)
5 ......... 1  (black)
6 ......... 1  (white)
7 ......... 1  (black) -> end

I hope I provide enough information needed for answers.

Please help me out to correct my code. Best regards Ondrej

Upvotes: 1

Views: 2180

Answers (1)

jnovacho
jnovacho

Reputation: 2903

I think you should redo your for cycle. It is correct, but too complicated. The problem with your code is on this line:

buffer[col] = next_black_color;

The variable col is always increasing, so the updated color count is added to the new slot in array. You cannot have 97 at position 5 in you example, because given your code, at position 5, you only processed 5 pixels.

Another slight problem with your code is, that you have two mutually exclusive conditions. If color < 127 and color > 127. First of all, if color is < 127, the else means that color is >=127. The equal sign is important! Your code would fail, if all colors would be 127.

Following is rough draft of the algorithm:

int arr[] = {0,0,180,180,180,180,180,180,180,180,180,0,0,0};
int size = 14;

bool last_dark = false;
bool current_dark = false;

if(arr[0] < 127){
    last_dark = true;
}

int counter = 0;
for(int i = 0; i < size; i++){
    if(arr[i] < 127){
        current_dark = true;
    } else {
        current_dark = false;
    }

            // is current pixel same shade as last?
    if(last_dark == current_dark){
        counter++;
    } else {
        cout << counter << endl;
        counter = 1; // the last color is already processed
    }
    last_dark = current_dark;
}
    // following line is important to get the last count
cout << counter << endl;

By no means it's complete. You will have to adapt to your needs. In the last if, we cannot compare last and current value directly, because 120 and 12 are both dark, but not same value. In your code replace the cout's with proper vector assignment, and don't forget the one outside the cycle. ;)

Regards,

jnovacho

Upvotes: 1

Related Questions