I'm a tad confused.
I am just getting started with OpenCV and its image data is pointed to by a char pointer. I can't quite work out how that works considering the actual data itself could be any number of data types, e.g. uint, float, double. As far as I knew, a pointer had to be of the same type as the pointer it represents.
It's probably w开发者_Python百科orth noting that openCV is a C library and my background is C++, so I am unaware of how these problems of needing variable types are solved in C.
For example the follwing code taken from Learning OpenCV illustrates my confusion:
void saturate_sv( IplImage* img ) {
for( int y=0; y<img->height; y++ ) {
uchar* ptr = (uchar*) (
img->imageData + y * img->widthStep
);
for( int x=0; x<img->width; x++ ) {
ptr[3*x+1] = 255;
ptr[3*x+2] = 255;
}
}
}
So this works, but when I try to operate on a iplImage of type IPL_DEPTH_64F and use ptr[3*x+1] = 1 The results are incorrect. So to distil my problems: how can I work on integer or floating point data through char pointers and specifically how could I rectify the above example to work with a double precision data.
Thanks
IPL_DEPTH_64F
ordouble
images will take care of the data from 0 - 1.- If you're used to C++ you should check out OpenCV2.0 which has several C++ classes and most importantly, one class, i.e.
Mat
to handle images, matrices, etc.
Here's a simple way to access elements in your image efficiently:
IplImage* img = cvCreateImage(cvSize(300,300),IPL_DEPTH_64F,1);
for( int y=0; y<img->height; y++ )
{
double* ptr = reinterpret_cast<double*>(img->imageData + y * img->widthStep);
for( int x=0; x<img->width; x++ )
{
ptr[x] = double(255);
}
}
cvNamedWindow("SO");
cvShowImage("SO",img);
cvWaitKey();
cvDestroyAllWindows();
cvReleaseImage(&img);
Since you're working with a double
image, it makes more sense to:
- Work with a
double
pointer so you can easily assign elements in a row withptr[x]
- Do the pointer arithmetic in bytes (
img->imageData + y * img->widthStep
) and the cast it to adouble
pointer
Also, it's important that you do the pointer arithmetic in bytes (or uchar
, i.e. unsigned char
) since OpenCV tends to pad the rows of the images with extra bytes for efficiency (especially for double
images).
So even if a double
element is 8 bytes, and you have, say, 300 rows, a row is not guaranteed to end at 8*300 or 2400 bytes since OpenCV might pad the end.
Therefore, this prevents you from initializing a pointer to the first element of the image and then using ptr[y*img->height+x]
to access elements since each row might have more than 8*(y*img->height)
bytes.
That's why the example code calculates the pointer to each row each time using img->widthStep
which represents the true size of each row in bytes.
OpenCV 2.0
If you use the Mat
class, you can do the same thing along these lines:
cv::Mat img(300,300,CV_64FC1);
for( int y=0; y<img.rows; y++ )
{
double* ptr = reinterpret_cast<double*>(img.data + y * img.step);
for( int x=0; x<img.cols; x++ )
{
ptr[x] = double(255);
}
}
cv::namedWindow("SO");
cv::imshow("SO",img);
cv::waitKey();
where img.step is the distance between successive rows in bytes
And if you want to directly access the element (slower):
img.at<double>(y,x)
精彩评论