【问题标题】:Access to image values using a Mat of coordinates (OpenCV/C++)使用坐标垫 (OpenCV/C++) 访问图像值
【发布时间】:2016-01-25 11:19:19
【问题描述】:

在 openCV(C++) 中,我有一个图像 IMG,我想提取存储在 coor 中位置的每个像素的值。是否有可能以有效的方式获取此像素值?一个foor循环(使用.at(i,j))是否有效?是否有一个内置函数可以做到这一点? 这是我的代码:

cv::Mat IMG = cv::imread("image.png",CV_LOAD_IMAGE_GRAYSCALE);
cv::Mat coor = (cv::Mat_<float>(3,2) << 1, 0, 0, 1, 2, 2); // search coordinates
cv::Mat pixel_values;
// and I'd like to do something like this:
//This should result in a matrix with the same size as *coor*
pixel_values = IMG.at(coor); // similar to the matrix accesing method in Matlab. 

【问题讨论】:

    标签: c++ opencv coordinates mat


    【解决方案1】:

    在 cv::Mat 中访问“像素”值的方法有多种。你读过 OpenCV 的文档吗?

    我建议你从here开始

    编辑 我已经更正了代码:此代码适用于 msvc 2015 和 opencv (3.1),但 > 2 也可以

    #include <iostream>
    #include <vector>
    #include <opencv2/opencv.hpp>
    #include <cstdint>
    using namespace std;
    
    #if defined(NDEBUG)
    #pragma comment(lib, "opencv_world310.lib")
    #else
    #pragma comment(lib, "opencv_world310d.lib")
    #endif // 
    
    
    cv::Mat GetPixelsFromMat( const cv::Mat& I, const std::vector<cv::Point2f>& points )
    {
        // some pre-condition:
        cv::Mat res( 1, (int)points.size( ), CV_8UC1 );
    
        int i = 0;
        for( const auto& point : points )
            res.ptr( 0 )[ i++ ] = I.at<uchar>( cvRound( point.y ), cvRound( point.x ) );
    
        return res;
    }
    
    int main( int argc, char* argv[] )
    {
        cv::Mat testImg( 1, 10, CV_8UC1 );
        for( int i = 0; i < 10; ++i )
            testImg.ptr( 0 )[ i ] = i;
    
        std::vector<cv::Point2f> points;
        points.push_back( cv::Point2f( 1, 0 ) );
        points.push_back( cv::Point2f( 5, 0 ) );
        points.push_back( cv::Point2f( 9, 0 ) );
    
        cv::Mat pixelsMap = GetPixelsFromMat( testImg, points );
    
        if( pixelsMap.ptr( 0 )[ 0 ] == 1 )
            cout << "OK 0" << endl;
        else
            cout << "FAIL 0" << endl;
    
        if( pixelsMap.ptr( 0 )[ 1 ] == 5 )
            cout << "OK 1" << endl;
        else
            cout << "FAIL 1" << endl;
    
        if( pixelsMap.ptr( 0 )[ 2 ] == 9 )
            cout << "OK 2" << endl;
        else
            cout << "FAIL 2";
    
    
        return EXIT_SUCCESS;
    }
    

    这是一个很大的简化,但我认为这是一个起点。

    【讨论】:

    • @Miki 未经测试就编写了它。上面的代码必须工作
    【解决方案2】:

    如果您已经知道矩阵的类型,则可以轻松使用 @elvis.dukaj answer。您只需要遍历您的坐标并检索相应的像素值。

    但是,如果您需要更通用的支持:

    • 任何类型和通道的输入矩阵
    • 坐标的输入列表可以是cv::Matstd::vector,具有任何类型的坐标(intfloat 等...)

    您可能会发现这个getPixels 函数很有用:

    #include <opencv2/opencv.hpp>
    using namespace cv;
    using namespace std;
    
    Mat getPixels(InputArray _src, InputArray _coords)
    {
        // Get src matrix
        Mat src = _src.getMat();
    
        // Get coords matrix, eventually convert to integer type
        Mat coords = _coords.getMat();
        if (coords.type() != CV_32S)
        {
            coords.convertTo(coords, CV_32S);
        }
        // Check coordinates
        int n = coords.checkVector(2, CV_32S);
        CV_Assert(n > 0);
    
        // Create output matrix
        Mat dst(n, 1, src.type());
    
        // Get pixel values at given coordinates
        int esz = src.elemSize();
        Point* coords_ptr = (Point*)coords.data;
        uchar* dst_ptr = dst.data;
    
        for (int i = 0; i < n; i++, dst_ptr += esz)
        {
            memcpy(dst_ptr, src.ptr(coords_ptr[i].y) + coords_ptr[i].x * esz, esz);
        }
    
        return dst;
    }
    
    
    int main() 
    {
    
        Mat img(5, 5, CV_8UC1);
        randu(img, Scalar(0, 0, 0), Scalar(10, 10, 10));
    
        vector<Point> coor{ Point(1, 0), Point(0, 1), Point(2, 2) };
        //cv::Mat coor = (cv::Mat_<float>(3, 2) << 1, 0, 0, 1, 2, 2);
    
        Mat out = getPixels(img, coor);
    
        cout << out;
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2015-08-10
      • 2014-01-03
      • 1970-01-01
      • 1970-01-01
      • 2013-10-10
      • 1970-01-01
      • 1970-01-01
      • 2018-03-26
      • 2014-11-05
      相关资源
      最近更新 更多