2016-03-08 2 views
2

Я пытаюсь очень просто с opencv, но получаю ошибку. Я просто пытаюсь прочитать 16-битное изображение png и получить доступ к конкретному значению пикселя. Я пробовал много способов, но не мог управлять значением get. Я использую OpenCV3.0 для Windows8 64bit.Значение изображения пикселя изображения OpenCV

ПРИМЕЧАНИЕ: при чтении изображения с использованием CV_LOAD_IMAGE_GRAYSCALE это нормально, но CV_LOAD_IMAGE_ANYDEPTH ошибка роста. Но когда я использую CV_LOAD_IMAGE_GRAYSCALE, мой самый высокий пиксель равен 9, что должно быть около 2000

Я загрузил пример изображения. example image

мой пример кода:

#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; 

}

Сообщение об ошибке:

Необработанное исключение при 0x00007FF8EB288A5C в OpenCVTest.exe: Microsoft C++ исключение: резюме :: Exception в ячейку памяти 0x000000A47F40F230.

Но я думаю, что это вводящая в заблуждение ошибка, я проверяю, что мое изображение 320 * 240, поэтому я уверен, что в этом месте есть пиксель.

Я попытался с скаляра также, но я получаю ту же ошибку

+0

вы определяете 'frame' дважды? – Thesane

+0

отправьте сообщение об ошибке пожалуйста. есть бесчисленные ошибки в этом мире – Piglet

+0

@Thsane это просто ошибка, пока я копирую свой код., ошибка такая же – seleucia

ответ

1

Пару вещей, которые вы должны заметить. Сначала вы определяете frame дважды.

второй, эта линия float zmx = frame.at<unsigned char>(118, 38); имеет пару вопросов. вы назначаете unsigned char на номер float. Также вы должны заметить, порядок обратный, чтобы получить доступ к значению x,y пикселя вы называете frame.at<unsigned char>(y, x), то лучший способ присвоить 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; 
} 

Update # 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

Как я прокомментировал ниже строку, также растущую ошибку, я пробовал с помощью Scalar, также ошибка такая же, даже без какого-либо назначения. Я получаю такую ​​же ошибку. – seleucia

+0

вы уверены, что изображение загружено в рамку ?? проверьте размер кадра после загрузки 'int rows = frame.rows; int cols = frame.cols; '. возможно, неправильный путь – Thesane

+0

Да, я печатал строки и столбцы, и я могу видеть эти значения при отладке – seleucia

2

Ваша самая большая проблема в том, что вы пытаетесь получить доступ к 16 BPP изображение, то есть в Mat типа CV_16U с неправильным типом данных. Вы должны использовать frame.at<ushort>(...) в случае одноканального 16-битного изображения (я предполагаю, что это имеет место здесь) или frame.at<Vec3w>(...) для изображений с 3 каналами.

Также вы должны убедиться, что правильно загрузили изображение. Используя imread с параметром IMREAD_GRAYSCALE, вы конвертируете свое изображение в 8bpp, чего вы не хотите. Вы должны использовать IMREAD_ANYDEPTH или IMREAD_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; 
} 
Смежные вопросы