如何/为什么为imageData存储为char - OpenCV的 [英] How/Why is imagedata stored as char - OpenCV

查看:379
本文介绍了如何/为什么为imageData存储为char - OpenCV的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一点点困惑。

我刚开始接触的OpenCV和图像数据是由一个字符指针指向。我不能完全制定出如何工作的考虑到实际数据本身可能是任何数量的数据类型,例如UINT,浮点型,双。据我所知,指针必须是相同类型的指针,重新presents的。

这也许值得一提的OpenCV的是C库和我的背景是C ++,所以我不知道如何需要的变量类型,这些问题用C都解决了。

例如来自OpenCV的学习采取的follwing code说明了我的困惑:

 无效saturate_sv(*的IplImage IMG){
    对于(INT Y = 0; Y< img->高度; Y ++){
    UCHAR * PTR =(UCHAR *)(
    img->的imageData + Y * img-> widthStep
    );
       对于(INT X = 0; X< img->宽度; X ++){
           ptr的[3 * X + 1] = 255;
           ptr的[3 * X + 2] = 255;
       }
    }
}

所以这个工作,但是当我尝试在类型IPL_DEPTH_64F的IplImage的操作使用PTR [3 * X + 1] = 1的结果是不正确的。因此,要提炼出自己的问题:我怎么能在整数或浮点数通过字符指针工作点数据,具体我怎么能纠正上面的例子有双precision数据进行工作。

感谢


解决方案

  1. IPL_DEPTH_64F 双击图像会照顾数据从0 - 1

  2. 如果你习惯了C ++,你应该看看 OpenCV2.0 其中有几个C ++类,最重要的一类,即来处理图像,矩阵等。

下面是访问图像有效元素的简单方法:

 的IplImage * IMG = cvCreateImage(cvSize(300,300),IPL_DEPTH_64F,1);
对于(INT Y = 0; Y< img->高度; Y ++)
    {
       双* PTR = reinter pret_cast<双* GT;(img->的imageData + Y * img-> widthStep);
       对于(INT X = 0; X< img->宽度; X ++)
       {
          PTR [X] =双(255);
       }
    }
cvNamedWindow(SO);
cvShowImage(SO,IMG);
cvWaitKey();
cvDestroyAllWindows();
cvReleaseImage(安培; IMG);

既然你正在使用一个双击图像,则更有意义:


  1. 双击指针,这样你就可以轻松地分配在一排的元素与 PTR工作[X]

  2. 请以字节为指针运算( img->的imageData + Y * img-> widthStep ),它要转换成指针

此外,它的重要你做字节(指针算术或 UCHAR ,即 unsigned char型),因为 OpenCV的趋于垫图片有额外的字节以效益为行(尤其是双击图像)。

所以,即使一个双击元素是8个字节,你有,比如说,300行,一行不能保证在8 * 300或2400个字节,因为结束OpenCV的威力垫结束。

因此​​,从初始化指针图像的第一元件,然后使用此prevents你 ptr的[Y * img->高度+ X] 访问元素,因为每行可能比 8 *(Y * img->高度)以上。字节

这是为什么例如code。使用每次计算指针到每一行 img-> widthStep 从而重新presents每一行的真实大小以字节计。

OpenCV的2.0

如果您使用类,你可以做同样的事情沿着这些路线:

  CV ::垫IMG(300,300,CV_64FC1);
对于(INT Y = 0; Y< img.rows; Y ++)
    {
       双* PTR = reinter pret_cast<双* GT;(img.data + Y * img.step);
       为(中间体X = 0; X&下; img.cols; X ++)
       {
          PTR [X] =双(255);
       }
    }
CV :: namedWindow(SO);
CV :: imshow(SO,IMG);
CV :: waitKey();

,其中img.step是字节连续行之间的距离

如果你想直接访问该元素(慢):

img.at<双>(Y,X)

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 worth 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

解决方案

  1. IPL_DEPTH_64F or double images will take care of the data from 0 - 1.
  2. 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:

  1. Work with a double pointer so you can easily assign elements in a row with ptr[x]
  2. Do the pointer arithmetic in bytes (img->imageData + y * img->widthStep) and the cast it to a double 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)

这篇关于如何/为什么为imageData存储为char - OpenCV的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆