【问题标题】:Access pixel value in a cvMat image in OpenCV在 OpenCV 中访问 c​​vMat 图像中的像素值
【发布时间】:2014-01-03 21:06:46
【问题描述】:

我使用 Canny 边缘检测器成功识别给定图像的边缘。我正在努力寻找这条检测到的边缘线上的特定点。

我的做法:

我在opencv中使用了cv::canny函数,输出以cv::Mat格式存储。我想遍历矩阵的所有值并识别存在边缘的所有像素,以便我可以检测到检测到的边缘线上的特定点。

使用的功能:

cv::Canny(frame_gray,contours,50,150);

输出存储在contours,类型为CV_8UC3

要访问像素值,试过了

contours.at<int>(i,j) != 0

还有

contours.at<uchar>(i,j) != 0

非常感谢上述帮助。如果方法是正确的并且遗漏了一些东西,或者我应该尝试另一种方法 谢谢

编辑:

for(int i=0;i<img_width;i++)
 { 
  if((int)contours.at<uchar>(i,neckcenter.y) > 0 ) 
  { 
    Point multipoints(i,neckcenter.y); 
    circle( contours, multipoints, neckpoint, Scalar( 255, 0, 0 ),4, 8, 0 );
    cout << (int)contours.at<uchar>(i,neckcenter.y) << endl; 
  }
 }

我正在使用上面的代码,它形成一个半径为 1 的小圆圈(由颈点定义),它在其中检测到一个点和边缘。颈部中心.y 是从早期计算得出的常数值。我在这里做错了什么?

代码的输出-

【问题讨论】:

    标签: c++ opencv image-processing


    【解决方案1】:

    在应用 Canny 之前,您可能需要一个灰度通道:

    Mat gray;
    cvtColor(bgr,gray,CV_BGR2GRAY); // now gray is a 8bit, uchar Mat
    
    Mat contours;
    cv::Canny(gray,contours,50,150);
    
    // now you're safe to use:
    uchar value = contours.at<uchar>(i,j);
    

    【讨论】:

    • 感谢您的回复...我使用了灰度通道(与您提到的相同),但仍然没有在边缘检测到点。该函数似乎无法读取边缘像素。将不胜感激任何建议.. 谢谢
    • 现在总的不同问题,不是吗?
    • 你能告诉我边缘存在的像素值范围是多少吗?因为在使用 uchar 时,值在终端中不是可读格式,而在使用 int 时,值范围从 255 到 1494300928
    • cout (i,j);// 哦,关于打印
    • 边缘值高,否则低
    【解决方案2】:

    语法:

    contours.at<uchar>(i,j)
    

    在数据类型(即灰度图像)方面对您的情况是正确的。这一行可能暗示了这个问题:

    for(int i=0;i<img_width;i++)
    

    当您使用at 访问OpenCV 像素时,您必须将像素位置指定为(row, col),因此您的索引是错误的。在您访问像素的所有地方尝试此操作:

    contours.at<uchar>(j,i)
    

    来自OpenCV documentation

    【讨论】:

    • thnx fr 回复..所以你建议我应该把if((int)contours.at&lt;uchar&gt;(i,neckcenter.y) &gt; 0 ) 变成if((int)contours.at&lt;uchar&gt;(neckcenter.y,i) &gt; 0 )?我试过了,但现在我在输出中没有得到任何分数。
    • @ShivangDoshi 好吧,您可能还有其他问题,但是颠倒您的 x 和 y 坐标肯定是一个主要问题。使用 img.at&lt;uchar&gt;(y,x) &gt; 0 是正确的测试 - 确保您现在在任何地方都使用正确的地址。
    • @ShivangDoshi 并非没有看到您修改后的代码 - 您确实确保您有 CV_8UC1 输出?在你的问题中你说CV_8UC3所以也许你错过了灰度转换?
    【解决方案3】:

    您有一个无符号字符类型的 3 通道图像。要访问它,您应该使用 cv::Vec3b 类型。操作方法如下:

    int channel = 0;//or 1 or 2
    contours.at<cv::Vec3b>(i,j)[channel]
    

    检查所有元素是否为0:

    contours.at<cv::Vec3b>(i,j)[0]==0 && contours.at<cv::Vec3b>(i,j)[1]==0 && contours.at<cv::Vec3b>(i,j)[2]==0
    

    但是你从哪里知道轮廓的图像类型是 CV_8UC3 的信息?

    【讨论】:

      猜你喜欢
      • 2013-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-18
      • 1970-01-01
      • 2012-02-14
      • 1970-01-01
      相关资源
      最近更新 更多