In openCV(C++) I have an image IMG and I'd like to extract the values of each pixel at positions store in coor . Is it possible to get this pixel values in an efficient way? Is a foor loop (using .at(i,j) ) efficient ?Is there a built-in function for doing this? This is my code:
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.
Threr are different ways to access the value of a "pixel" in a cv::Mat. Have you read the documentation of OpenCV?
I suggest you to start form here
I've corrected the code: this code works with msvc 2015 and opencv (3.1) but also > 2 is ok 我已经更正了代码:此代码适用于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;
}
This is a big semplification but I think it's a starting point.
If you already know the type of your matrix, you can easily go with @elvis.dukaj answer . You just need to iterate over your coordinates and retrieve corresponding pixel value.
But, if you need something more general that supports:
cv::Mat
or a std::vector
, with coordinates of any type ( int
, float
, etc...) you may find this getPixels
function useful:
#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;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.