【问题标题】:How can retrieve pixel value using CvMat如何使用 CvMat 检索像素值
【发布时间】:2015-02-19 10:14:55
【问题描述】:
img->data.ptr[i,j]=img1.data.ptr[(m_c*w_in)+n_c];

我试过了,但它只显示了一个值。 任何帮助都将不胜感激。

【问题讨论】:

    标签: c++ opencv


    【解决方案1】:

    首先,您为什么要使用旧界面。如果您有新的 opencv,则将 CvMat 转换为 cv::Mat,然后执行操作。完成后,您可以将 Mat 转换回 CvMat。

    【讨论】:

      【解决方案2】:

      首先切换到cv::Mat 然后,您有几种方法可以访问像素 x,y:

      cv::Mat img;
      int x,y;
      
      //[...] Initialize here x and y
      
      cv::Point p(x,y);
      int stride = img.step1();
      
      //All of these are valid ways to access pixel x,y
      img.at<uint8_t>(y,x); //Or, for example, cv::Vec3b in place of uint8_t in case of color images
      img.at<uint8_t>(p);
      //The following are valid only for grayscale 8-bit images, otherwise they have to be modified a bit
      img.ptr(y)[x];
      img.ptr()[y * stride + x]; 
      

      事实上,一旦您切换到 cv::Mat,您可以在 OpenCV get pixel channel value from Mat imageAccessing certain pixel RGB value in openCV 找到其他广泛的答案

      【讨论】:

      • ^^^ptr 版本也需要一个类型。
      • @berak 如果您使用的是灰度 8 位图像,则不会
      • @Antonio 非常感谢您的建议,但我找到了解决方案并发布了它,以便一些人得到帮助。
      【解决方案3】:

      这是一个老问题,只适用于没有奢侈使用较新的 cv:mat 格式并且必须使用 cvmat 访问像素的任何人。使用 OpenCV 1.1 测试。

      static unsigned long get_color(IplImage *img, CvPoint* pt, double *luma) {
          uchar blue, green, red;
          unsigned long color = 0;
          CvMat hdr; 
          CvMat *mat = cvGetMat(img, &hdr);
          int col = mat->step / mat->cols;
          uchar *pix = mat->data.ptr + (pt->y * mat->step + pt->x * col);
      
          if (col == 1) {
              // Grayscale
              color = *pix;
              blue = color * 11 / 100;
              green = color * 59 / 100;
              red = color * 30 / 100;
          } else if (col == 3) {
              // 3 channel RGB
              blue = *pix;
              green = *(pix + 1);
              red = *(pix + 2); 
              color = red << 16 | green << 8 | blue;
          } else {
              printf("Unsupported number of channel %d\n", col);
              return 0;
          }
      
          if (luma) 
              *luma = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
      
          printf("\n\nb=%x g=%x, r=%x color=%x\n", blue, green, red, color);
          printf("cols=%d, step=%d, col=%d, x=%d, y=%d loc=%d\n", 
                 mat->cols, mat->step, col, pt->x, pt->y,
                 (pt->y * mat->step + pt->x * col));
          return color;
      }
      

      输出:

      1. Output from a grayscaled 600x600 Red.jpeg file
      // Pixel (0,0)
      b=8 g=2c, r=16 color=4c
      cols=600, step=600, col=1, x=0, y=0 loc=0
      
      // Pixel (1,0)
      b=8 g=2c, r=16 color=4c
      cols=600, step=600, col=1, x=1, y=0 loc=1
      
      // Pixel (1,1)
      b=8 g=2c, r=16 color=4c
      cols=600, step=600, col=1, x=1, y=1 loc=601
      
      
      2. Output from a 3 channel rgb 600x600 Red.jpeg file
      // Pixel (0,0)
      b=0 g=0, r=fe color=fe0000
      cols=600, step=1800, col=3, x=0, y=0 loc=0
      
      // Pixel (1,0)
      b=0 g=0, r=fe color=fe0000
      cols=600, step=1800, col=3, x=1, y=0 loc=3
      
      // Pixel (1,1)
      cols=600, step=1800, col=3, x=1, y=1 loc=1803
      b=0 g=0, r=fe color=fe0000
      

      【讨论】:

        【解决方案4】:

        要使用 CvMat 访问数据,你必须使用 "img->data.ptr[x*col+y]" 它可以用来存储 uchar 的数据。 CvMat 还支持 double、float、string 和 integer 类型。因此,您可以根据自己的说服力存储数据。

        【讨论】:

        • x*col 是不安全的,因为属于同一列(“步幅”或“步幅”)的 2 个相邻像素之间的字节距离可能与列数不同(顺便说一下,您应该将变量命名为cols,而不是col)。我不知道在哪里可以找到CvMat 文档,所以我不知道步幅值保存在哪里(在我的回答中有一个cv::Mat 的示例),可能在step 字段中。
        • CvMatcv::Mat 之间的转换是 so straightforward (高效,没有内存副本),我不明白你为什么要为此挣扎并继续使用过时的东西。无论如何,如果你真的需要 CvMat 的文档,你可以找到它here。实际上,步幅在step 字段中。请注意,stride != cols 也适用于 8 位灰度图像,例如因为关于内存对齐的选择。
        猜你喜欢
        • 2012-10-05
        • 1970-01-01
        • 2012-12-03
        • 2012-09-23
        • 2010-11-05
        • 2011-05-03
        • 2011-02-05
        • 1970-01-01
        相关资源
        最近更新 更多