Ask Your Question
0

working with pixel in Mat

asked 2014-07-25 05:03:27 -0600

jamesnzt gravatar image

i run the following program for copying image pixel by pixel

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

using namespace cv;
using namespace std;

int main (int argc, char** argv)
{
 if (argc!=2)
{
 cout <<"Usage: specify the image"<<endl;
return -1;
}
Mat img=imread(argv[1],CV_LOAD_IMAGE_COLOR);
Mat A(img.size(),img.type());
if(!img.data)
{
cout<<"could not open or find the image"<<endl;
return -1;
}

namedWindow("Display window",0);
//namedWindow("gray",0);
namedWindow("threshold",0);
imshow("Display window",A);

for (int i=0;i<img.rows;i++)
{
for(int j=0;j<img.cols;j++)
{
Vec3f intensity = img.at<Vec3f>(i,j);
float blue=intensity.val[0];
float green=intensity.val[1];
float red=intensity.val[2];

A.data[A.channels()*(A.cols*i + j) + 0] = blue;
A.data[A.channels()*(A.cols*i + j) + 1] = green;
A.data[A.channels()*(A.cols*i + j) + 2] = red;
    }
}

//cout<<red<<","<<blue<<","<<green<<endl;
imwrite("etc1.png",A);
imshow("threshold",A);
waitKey(0);

}

input image

image description

output image

image description

where is the mistake?

edit retag flag offensive close merge delete

Comments

I think , you first need to creak a image with zeros of same size and type .

FLY gravatar imageFLY ( 2014-07-25 05:51:42 -0600 )edit

2 answers

Sort by ยป oldest newest most voted
1

answered 2014-07-25 13:48:23 -0600

rwong gravatar image

It is a type mismatch.

The first matrix cv::Mat img which is loaded from the file, is a 2D matrix of type cv::Vec3b. This means each pixel is stored as a tuple of 3 bytes (which has the same memory layout as uchar[3], or cv::Vec<uchar, 3>.

The template <T> Mat.at<T>() function does not perform any conversion at all. That means you have to use the correct type for the template argument. If the type is not correct, the result is undefined.

The following line of code,
Vec3f intensity = img.at<vec3f>(i,j);
tells C++ to reinterpret the next 12 bytes (3 * sizeof(float)) as the bit patterns for IEEE-754 single-precision float, and return their values.

However, the matrix img is actually an array of bytes, so the interpretation will return meaningless values.

Due to the way C++ and OpenCV are designed, Mat.at<T> does not give a compiler warning or error when it is used in the wrong way.

The only allowed way to get the pixel value from Mat img is
cv::Vec3f intensity = img.at<cv::vec3b>(i,j);
Notice that at<T>(i, j) is called with the same type as Mat img, and then an implicit type conversion from cv::Vec3b to cv::Vec3f occurs.

edit flag offensive delete link more
3

answered 2014-07-25 06:52:59 -0600

FLY gravatar image

updated 2014-07-25 12:03:14 -0600

Below code work for me on your image , it looks your performing functions which are not compulsory to perform in copying image using pixel operation

int main (int argc, char** argv)
{

Mat img=imread("D:\\32.png",CV_LOAD_IMAGE_COLOR);
Mat A = Mat::zeros(img.size(),img.type());

namedWindow("Display window");

namedWindow("threshold");
imshow("Display window",img);
for (int i = 0; i < img.size().height; ++i)
{
  for(int j = 0; j < img.size().width; ++j)
    {   
       A.at<Vec3b>(i,j) = img.at<Vec3b>(i,j);
    }
}
imwrite("D:\\etc1.png",A);
imshow("threshold",A);
waitKey(0);

}

input image

image description

output image

image description

edit flag offensive delete link more

Question Tools

Stats

Asked: 2014-07-25 05:03:27 -0600

Seen: 4,869 times

Last updated: Jul 25 '14