How to access elements of Cvmat* in opencv - opencv

How can I print the numbers stored in CVmat* in opencv?
I am facing a problem in accessing elements of cvmat. Please suggest a solution!

here with i have given exp code ..its may be helpful for u...
CvMat mathdr, *mat = cvGetMat( img1, &mathdr );
CvSize size_im = cvGetSize(img1);
unsigned int M = img1->height;
unsigned int N = img1->width;
for(i=0;i<M;i++)
{
for (j =0;j<N;j++)
{
CvScalar scal = cvGet2D(mat,i,j);
printf("pixel val of the image is:%f %f %f\n",scal.val[0],scal.val[1],scal.val[3]);
}
}

In answer to your comment to aranga,
i am not getting why have u used three scal.val[0],scal.val[1],scal.val[3]); only scal.val[0] is showing output scal.val[1] and scal.val[2] are just giving zeros
this depends on your image, or more precisely on how many channels it has. A normal image will have 3 channels (RGB, though it is actually in reverse, so BGR), yours seems to be grayscale, or in anycase have only values in the first channel.
And I've just checked, indeed if you perform
cvtColor(src,dst,CV_RGB2GRAY);
to convert a three-channel RGB image into grayscale, the grayscale image has only 1 channel. But perhaps you would know why your image is only using 1 channel...

Related

Convert color image into grey in opencv without CV_RGB2GRAY

I want to convert colorBGR image into grey scale in opencv without using direct command CV_RGB2GRAY. Here I uploaded my code which gives me a bluish color of the image which is not a proper grey output image. Please check the below code and tell me where I m going wrong or you can give me another solution to convert the color image into grey output image without CV_RGB2GRAY.
Thanks in advance.
Mat image=imread("Desktop\\Sample input\\ip1.png");
Mat grey( image.rows,image.cols, CV_8UC3);
for(int i=0;i<image.rows;i++)
{
for(int j=0;j<image.cols;j++)
{
int blue = image.at<Vec3b>(i,j)[0];
int green = image.at<Vec3b>(i,j)[1];
int red = image.at<Vec3b>(i,j)[2];
grey.at<Vec3b>(i,j) = 0.114*blue+0.587*green+ 0.299*red ;
}
}
imshow("grey image",grey);
If you intend to convert the image which you are taking by imread() functions, you can take the image as input as a grayscale image directly by
Mat image = imread("Desktop\\Sample input\\ip1.png",CV_LOAD_IMAGE_GRAYSCALE);
or, by
Mat image = imread("Desktop\\Sample input\\ip1.png",0);
It is because CV_LOAD_IMAGE_GRAYSCALE corresponds to the constant 0. And when in imread() function gets this argument zero, it will load an image with intensity one.
And if want to convert any image to grayscale then the out image image should like
Mat grey = Mat::zeros(src_image.rows, src_image.cols, CV_8UC1);
as grayscale image is of only one channel and then you can convert the image like this:
for(int i=0;i<image.rows;i++)
{
for(int j=0;j<image.cols;j++)
{
int blue = image.at<Vec3b>(i,j)[0];
int green = image.at<Vec3b>(i,j)[1];
int red = image.at<Vec3b>(i,j)[2];
grey.at<uchar>(i, j) = (uchar) (0.114*blue + 0.587*green + 0.299*red);
}
}
It will give you the grayscale image.
In your code, the grey Mat has 3 channels. For a grayscale image you only need 1 channel (8UC1).
Also, when you are writing the values in the grayscale image, you need to use uchar instead of Vec3b because each pixel in the grayscale image is only made up of one unsigned char value, not a vector of 3 values.
So, you need to replace these lines:
Mat grey(image.rows, image.cols, CV_8UC1);
and
grey.at<uchar>(i, j) = 0.114*blue + 0.587*green + 0.299*red;

Preventing information loss on image subtraction

I have two images that I am subtracting from one another quite simply:
Mat foo, a, b;
...//imread onto a and b or somesuch
foo = a - b;
Now, as I understand it, any pixel value that goes into the negatives (or over 255 for that matter) will be set to zero instead. If that is so, I'd like to know if there is any way to permit it to go under zero so that I may adjust the image later without information loss.
I'm working with greyscale images if that simplifies things.
This is how a simple convert => substract => convertAndScaleBack application would look like:
input:
and
int main()
{
cv::Mat input = cv::imread("../inputData/Lenna.png", CV_LOAD_IMAGE_GRAYSCALE);
cv::Mat input2 = cv::imread("../inputData/Lenna_edges.png", CV_LOAD_IMAGE_GRAYSCALE);
cv::Mat input1_16S;
cv::Mat input2_16S;
input.convertTo(input1_16S, CV_16SC1);
input2.convertTo(input2_16S, CV_16SC1);
// compute difference of 16 bit signed images
cv::Mat diffImage = input1_16S-input2_16S;
// now you have a 16S image that has some negative values
// find minimum and maximum values:
double min, max;
cv::minMaxLoc(diffImage, &min, &max);
std::cout << "min pixel value: " << min<< std::endl;
cv::Mat backConverted;
// scale the pixel values so that the smalles value is 0 and the largest one is 255
diffImage.convertTo(backConverted,CV_8UC1, 255.0/(max-min), -min);
cv::imshow("backConverted", backConverted);
cv::waitKey(0);
}
output:

OpenCV 2.4.2 Byte array to Mat produces a strange image pattern

Good afternoon,
I am trying to run OpenCV through a DLL and use it in a LabVIEW application.
I have correctly acquired an image in LV and passed the byte array to the DLL.
I can loop and print out in a text file the values for every pixel and match them to the output in LV, so I know that all my pixels are in the right position, for the exception that LV adds 2 columns at the beginning, with the first 2 values reserved for height and width and the rest are arbitrary numbers. But all this should do is produce a streak on the left side of the image.
Next, I am using the following lines to convert and display the image.
a[0], a[1]... etc. are channels.
The output image comes out as a very horizontally stretched out image with pixels spaced equally 15-20 pixels apart and surrounded by black pixels. I attached a screenshot
_declspec (dllexport) double imageProcess(int **a, int &x, int &y, int &cor,int &cog,int &cob,int &cow, int th, int hth)
{
y = a[0][0];
x = a[0][1];
Mat image(y, x, CV_8U, a[0]);
namedWindow( "Display window", CV_WINDOW_NORMAL ); // Create a window for display.
imshow( "Display window", image ); // Show our image inside it.
return (0);
}
Additionally I tried using this code with the same effect:
IplImage* cv_image = cvCreateImageHeader(cvSize(x,y), IPL_DEPTH_8U, 1);
cvSetData(cv_image, a[0], cv_image->widthStep);
Mat image = Mat(cv_image, false);
Can anyone please help me explain why this is happening during my image creation?
Note, Unfortunately, I cannot provide the original image/capture from LV, but I can say that it doesn't look anything like that and I am working with everything in grayscale.
Output Image:
your input ( a ) is a matrix of ints, while opencv wants uchars there.
the way you do it currently, each int (from a) gets spread over 4 consecutive bytes,
( that's exactly, what i see in that picture )
also it's only using the 1st 1/4 of the input data
you probably won't get away with just feeding the pixel pointer into your cv::Mat there,
looping over a[0], casting each pixel to uchar, and then assigning it to the opencv-pixel
should work, imho
You could convert your image to uchar or simple use an int image by replacing CV_8U by CV_32S and then:
int offset = 0;
int scale = 0;
cv::Mat image8U;
image.convertTo(image8U, CV_8UC1, scale, offset );

how to separate BGR components of a pixel in color image using openCV

Since each pixel memory contains 8 bit for each component Blue,Green and Red. So how can I separate these components from Image or Image Matrix. As
int Blue = f(Image(X,y));// (x,y) = Coordinate of a pixel of Image
similarly, for red and green.
So what should be function f and 2D matrix Image;
Thanks in advance
First off, you must go through the basics of OpenCV and turn your attention towards other parts of image processing. What you ask for is pretty basic and assuming you will be using OpenCV 2.1 and higher,
cv::Mat img = Read the image off the disk or do something to fill the image.
To access the RGB values
img.at<cv::Vec3b>(x,y);
But would give the values in reverse that is BGR. So make sure you note this.
Basically a cv::Vec3b type that is accessed.
img.at<cv::Vec3b>(x,y)[0];//B
img.at<cv::Vec3b>(x,y)[1];//G
img.at<cv::Vec3b>(x,y)[2];//R
or
Vec3f pixel = img.at<Vec3f>(x, y);
int b = pixel[0];
int g = pixel[1];
int r = pixel[2];
Now onto splitting the image into RGB channels you can use the following
Now down to primitive C style of OpenCV (There C and C++ style supported)
You can use the cvSplit function
IplImage* rgb = cvLoatImage("C://MyImage.bmp");
//now create three single channel images for the channel separation
IplImage* r = cvCreateImage( cvGetSize(rgb), rgb->depth,1 );
IplImage* g = cvCreateImage( cvGetSize(rgb), rgb->depth,1 );
IplImage* b = cvCreateImage( cvGetSize(rgb), rgb->depth,1 );
cvSplit(rgb,b,g,r,NULL);
OpenCV 2 CookBook Is one of the best books on OpenCV. Will help you alot.

How to convert an 8-bit OpenCV IplImage* to a 32-bit IplImage*?

I need to convert an 8-bit IplImage to a 32-bits IplImage. Using documentation from all over the web I've tried the following things:
// general code
img2 = cvCreateImage(cvSize(img->width, img->height), 32, 3);
int height = img->height;
int width = img->width;
int channels = img->nChannels;
int step1 = img->widthStep;
int step2 = img2->widthStep;
int depth1 = img->depth;
int depth2 = img2->depth;
uchar *data1 = (uchar *)img->imageData;
uchar *data2 = (uchar *)img2->imageData;
for(h=0;h<height;h++) for(w=0;w<width;w++) for(c=0;c<channels;c++) {
// attempt code...
}
// attempt one
// result: white image, two red spots which appear in the original image too.
// this is the closest result, what's going wrong?!
// see: http://files.dazjorz.com/cache/conversion.png
((float*)data2+h*step2+w*channels+c)[0] = data1[h*step1+w*channels+c];
// attempt two
// when I change float to unsigned long in both previous examples, I get a black screen.
// attempt three
// result: seemingly random data to the top of the screen.
data2[h*step2+w*channels*3+c] = data1[h*step1+w*channels+c];
data2[h*step2+w*channels*3+c+1] = 0x00;
data2[h*step2+w*channels*3+c+2] = 0x00;
// and then some other things. Nothing did what I wanted. I couldn't get an output
// image which looked the same as the input image.
As you see I don't really know what I'm doing. I'd love to find out, but I'd love it more if I could get this done correctly.
Thanks for any help I get!
The function you are looking for is cvConvertScale(). It automagically does any type conversion for you. You just have to specify that you want to scale by a factor of 1/255 (which maps the range [0...255] to [0...1]).
Example:
IplImage *im8 = cvLoadImage(argv[1]);
IplImage *im32 = cvCreateImage(cvSize(im8->width, im8->height), 32, 3);
cvConvertScale(im8, im32, 1/255.);
Note the dot in 1/255. - to force a double division. Without it you get a scale of 0.
Perhaps this link can help you?
Edit In response to the second edit of the OP and the comment
Have you tried
float value = 0.5
instead of
float value = 0x0000001;
I thought the range for a float color value goes from 0.0 to 1.0, where 1.0 is white.
Floating point colors go from 0.0 to 1.0, and uchars go from 0 to 255. The following code fixes it:
// h is height, w is width, c is current channel (0 to 2)
int b = ((uchar *)(img->imageData + h*img->widthStep))[w*img->nChannels + c];
((float *)(img2->imageData + h*img2->widthStep))[w*img2->nChannels + c] = ((float)b) / 255.0;
Many, many thanks to Stefan Schmidt for helping me fix this!
If you do not put the dot (.), some compilers will understand is as an int division, giving you a int result (zero in this case).
You can create an IplImage wrapper using boost::shared_ptr and template-metaprogramming. I have done that, and I get automatic garbage collection, together with automatic image conversions from one depth to another, or from one-channel to multi-channel images.
I have called the API blImageAPI and it can be found here:
http://www.barbato.us/2010/10/14/image-data-structure-based-shared_ptr-iplimage/
It is very fast, and make code very readable, (good for maintaining algorithms)
It is also can be used instead of IplImage in opencv algorithms without changing anything.
Good luck and have fun writing algorithms!!!
IplImage *img8,*img32;
img8 =cvLoadImage("a.jpg",1);
cvNamedWindow("Convert",1);
img32 = cvCreateImage(cvGetSize(img8),IPL_DEPTH_32F,3);
cvConvertScale(img8,img32,1.0/255.0,0.0);
//For Confirmation Check the pixel values (between 0 - 1)
for(int row = 0; row < img32->height; row++ ){
float* pt = (float*) (img32->imageData + row * img32->widthStep);
for ( int col = 0; col < width; col++ )
printf("\n %3.3f , %3.3f , %3.3f ",pt[3*col],pt[3*col+1],pt[3*col+2]);
}
cvShowImage("Convert",img32);
cvWaitKey(0);
cvReleaseImage(&img8);
cvReleaseImage(&img32);
cvDestroyWindow("Convert");

Resources