1
votes

I am just starting to use the Open CV library and one of my first code is a simple negative transform function.

#include <stdio.h>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

void negative(Mat& input,Mat& output)
{
  int row = input.rows;
  int col = input.cols;
  int x,y;
  uchar *input_data=input.data;
  uchar *output_data= output.data;


  for( x=0;x<row;x++)
    for( y=0;y<col;y++)
      output_data[x*col+y]=255-input_data[x*col+y];

    cout<<x<<y;



}

int main( int argc, char** argv )
{
  Mat image;
  image = imread( argv[1], 1 );

  Mat output=image.clone();

  negative(image,output);

  namedWindow( "Display Image", CV_WINDOW_AUTOSIZE );
  imshow( "Display Image", output );

  waitKey(0);

  return 0;
}

I have added the extra line to check if the entire image is processed. The problem i am facing with my output image is that negative transform is applied only to top half of the image.

Now what happens is that the values for x and y are displayed only after i press a key (i.e. once the image is shown)

My question is why is the window being called before the function is executed ?

2

2 Answers

2
votes

The fundamental problem in your code is that you are reading in a color image but you try to process it as grayscale. Therefore the indices shift and what really happens is that you only process the first third of the image (because of the 3-channel format).

See opencv imread manual

flags – Specifies color type of the loaded image:
>0 the loaded image is forced to be a 3-channel color image
=0 the loaded image is forced to be grayscale

You've specified flags=1.

Here's a way of doing it:

Vec3b v(255, 255, 255);
for(int i=0;i<input.rows;i++) //search for edges
{
    for (int j=0 ;j<input.cols;j++)
    {
        output.at<Vec3b>(i,j) = v - input.at<Vec3b>(i,j);
    }
}

Note that here Vec3b is a 3-channel pixel value as opposed to uchar which is a 1-channel value.
For a more efficient implementation you can have a look at Mat.ptr<Vec3b>(i).

EDIT: If you are processing lots of images, for a general iteration over the pixels the fastest way is:

Vec3b v(255, 255, 255); // or maybe Scalar v(255,255,255) Im not sure
for(int i=0;i<input.rows;i++) //search for edges
{
    Vec3b *p=input.ptr<Vec3b>(i);
    Vec3b *q=output.ptr<Vec3b>(i);
    for (int j=0 ;j<input.cols;j++)
    {
        q[j] = v - p[j];
    }
}

See "The OpenCV Tutorials" -- "The efficient way" section.

1
votes

Try to write:

cout << x << y << endl;

The function is called before, but the output is not flushed directly, which results in your image appearing before the text is written. By adding an "endline", you force a flush. You could also use flush(cout); instead of adding and endline.


For the negative, you can use the OpenCV function subtract() directly:

subtract(Scalar(255, 255, 255), input, output);