OpenCV阅读图像的像素值

问题描述:

我想用opencv很简单的事情,但得到错误。 我只是想读取16位PNG图像和访问特定的像素值。我尝试了很多方法,但无法管理获得价值。我在windows8 64bit上使用OpenCV3.0。OpenCV阅读图像的像素值

注意:虽然使用CV_LOAD_IMAGE_GRAYSCALE读取图像很好,但CV_LOAD_IMAGE_ANYDEPTH上升错误。但是,当我使用CV_LOAD_IMAGE_GRAYSCALE我的最高像素是9,这应该是2000左右

我上传的示例图像。​​

我的例子的代码:

#include "opencv2/core/core.hpp" 
#include "opencv2/imgproc/imgproc.hpp" 
#include "opencv2/highgui/highgui.hpp" 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
cv::Mat frame = cv::imread("filepath", CV_LOAD_IMAGE_ANYDEPTH);//using CV_LOAD_IMAGE_GRAYSCALE is fine, but CV_LOAD_IMAGE_ANYDEPTH rising error 
frame.convertTo(frame, CV_16U);// to be sure... i omitted this part also and same error 
double min, max; 
cv::Point mloc, mxloc; 
cv::minMaxLoc(frame, &min, &max, &mloc, &mxloc); 
//i can access min and max values but not the specific pixel value 
float zmx = frame.at<unsigned char>(118, 38);//rise error 
float zm = frame.at<float>(30,40);//rise error 
return 0; 

}

错误消息:Microsoft C++异常:

在0x00007FF8EB288A5C在OpenCVTest.exe未处理的异常CV ::异常在存储器位置0x000000A47F40F230。

但我认为这是误导性的错误,我检查了我的图像是320 * 240,所以我确定在那个位置有像素。

我试过标量还,但我得到同样的错误

+0

要定义两次'frame'? – Thesane

+0

请发布错误消息。在这个世界上有无数的错误 – Piglet

+0

@Thsane它只是错误,而我coppying我的代码。,错误是相同的 – seleucia

一对夫妇的事情,你应该注意。 首先你要定义frame两次。

秒,这条线float zmx = frame.at<unsigned char>(118, 38);有几个问题。您将unsigned char分配给float。还应该注意的顺序颠倒来访问你打电话frame.at<unsigned char>(y, x)x,y像素值,那么最好的方式分配给Scalar,而不是像这样

Scalar fmx = frame.at<uchar>(118, 38); 

或使用Point为了避免混淆

Scalar fmx = frame.at<uchar>(Point(38,118)); 

最后一件事,确保正确加载图像和frame具有图像数据


UPDATE

我只是测试你的代码,它工作得很好(以下检查),我想不出任何东西,但在提供的路径没有找到图像

#include "opencv2/core/core.hpp" 
#include "opencv2/imgproc/imgproc.hpp" 
#include "opencv2/highgui/highgui.hpp" 

int main(int argc, char** argv) 
{ 
    cv::Mat frame = cv::imread("0FD0X.png", CV_LOAD_IMAGE_GRAYSCALE); 
    frame.convertTo(frame, CV_16U);// to be sure... i omitted this part also and same error 
    double min, max; 
    cv::Point mloc, mxloc; 
    cv::minMaxLoc(frame, &min, &max, &mloc, &mxloc); 
    //i can access min and max values but not the specific pixel value 
    float zmx = frame.at<unsigned char>(118, 38);// no error 
    float zm = frame.at<float>(30, 40);// no error 
    std::cout << zmx << std::endl; // out 0 
    std::cout << min << std::endl; // out 0 
    std::cout << max << std::endl; // out 9 
    std::cout << mloc << std::endl; // out [0,0] 
    std::cout << mxloc << std::endl; // out [125,30] 
    return 0; 
} 

更新#2访问您需要使用Vec3b数据类型访问的多通道图像。还要注意点坐标的顺序。检查下面的代码

#include "opencv2/core/core.hpp" 
#include "opencv2/imgproc/imgproc.hpp" 
#include "opencv2/highgui/highgui.hpp" 

int main(int argc, char** argv) 
{ 
    cv::Mat frame = cv::imread("0FD0X.png", CV_LOAD_IMAGE_ANYDEPTH); 
    frame.convertTo(frame, CV_16U);// to be sure... i omitted this part also and same error 
    double min, max; 
    cv::Point mloc, mxloc; 
    cv::minMaxLoc(frame, &min, &max, &mloc, &mxloc); 
    //i can access min and max values but not the specific pixel value 
ushort pValShort = frame.at<ushort>(38, 118);// no error 
Vec3b pValVec = frame.at<Vec3b>(38, 118);// no error 
Vec3b pValVecPoint = frame.at<Vec3b>(Point(118,38));// no error 
std::cout << pValShort << std::endl; // out 2423 
std::cout << pValVec << std::endl; // out [166,8,165] 
std::cout << pValVecPoint << std::endl; // out [166,8,165] 

    std::cout << min << std::endl; // out 0 
    std::cout << max << std::endl; // out 2423 
    std::cout << mloc << std::endl; // out [0,0] 
    std::cout << mxloc << std::endl; // out [118,38] 
    return 0; 
} 
+0

正如我评论下线也上升的错误,我试着与标量也错误是一样的,即使没有任何分配我得到相同的错误 – seleucia

+0

你确定图像加载到框架?加载完成后检查帧大小int rows = frame.rows; int cols = frame.cols;'。也许是错误的路径 – Thesane

+0

是的,我打印行和列,我可以看到这个值在调试 – seleucia

你最大的问题是,你试图访问一个16 BPP图像,即与错误的数据类型类型CV_16UMat。如果是单通道16 bpp图像(我想这里是这种情况),或者对于3通道图像,应该使用frame.at<ushort>(...)

此外,您应该确保您正确加载图像。使用imread与参数IMREAD_GRAYSCALE你正在转换你的图像8bpp,这不是你想要的。您应该使用IMREAD_ANYDEPTHIMREAD_UNCHANGED

看看这个代码:

#include<opencv2/opencv.hpp> 

int main() 
{ 
    // Read the image as original bpp 
    cv::Mat frame = cv::imread("path_to_image", cv::IMREAD_ANYDEPTH); 

    // Be sure that the image is loaded 
    if (frame.empty()) 
    { 
     // No image loaded 
     return -1; 
    } 

    // Be sure that the image is 16bpp and single channel 
    if (frame.type() != CV_16U || frame.channels() != 1) 
    { 
     // Wrong image depth or channels 
     return -1; 
    } 


    double min_val, max_val; 
    cv::Point min_loc, max_loc; 
    cv::minMaxLoc(frame, &min_val, &max_val, &min_loc, &max_loc); 

    // Access values with correct data type 
    ushort zmx = frame.at<ushort>(max_loc); 

    return 0; 
}