OpenCV не распознает размер мата

Я пытаюсь распечатать изображение с помощью OpenCV, определяя мат 400x400:

plot2 = cv::Mat(400,400, CV_8U, 255);

Но когда я пытаюсь распечатать точки, происходит что-то странное. Координата y печатается только для первых 100 значений. То есть, если я печатаю точку (50,100), она печатается не в 100/400-й части столбца, а в конце. Каким-то образом 400 столбцов превратились в 100.

Например, при запуске этого:

for (int j = 0; j < 95; ++j){
    plot2.at<int>(20, j) = 0;
}
cv::imshow("segunda pared", plot2);

Показывает это (подчеркнутая часть - это часть, соответствующая приведенному выше коду):

ИЗОБРАЖЕНИЕ

Линия до 95 занимает почти все 400 точек, тогда как она должна занимать только 95/400 экрана.

Что я делаю неправильно?


person user6375350    schedule 27.05.2016    source источник


Ответы (1)


Когда вы определили свой cv::Mat, вы четко сказали, что он от типа CV_8U:

plot2 = cv::Mat(400,400, CV_8U, 255);

Но когда вы пытаетесь распечатать его, вы говорите, что это тип int, который обычно является 32-битным со знаком, а не 8-битным без знака. Итак, решение:

for (int j = 0; j < 95; ++j){
    plot2.at<uchar>(20, j) = 0;
}

Важное примечание: имейте в виду, что OpenCV использует стандартные типы C ++, а не фиксированные. Таким образом, нет необходимости использовать типы фиксированного размера, такие как uint16_t или аналогичные. потому что при компиляции OpenCV и вашего кода на другой платформе они оба изменятся вместе.


Кстати, один из хороших способов перебрать ваш cv::Mat:

for (size_t row = 0; j < my_mat.rows; ++row){
    auto row_ptr=my_mat.ptr<uchar>(row);
    for(size_t col=0;col<my_mat.cols;++col){
         //do whatever you want with  row_ptr[col]  (read/write)
    }
}
person Humam Helfawi    schedule 27.05.2016
comment
Вы уверены в разделе "Важное примечание"? Можете ли вы предоставить источник этой информации? Вы хотите сказать, что если вы создадите изображение как plot2 = cv::Mat(400,400, CV_16U, 255);, доступ с помощью plot2.at<uint16_t>(20, j) = 0; будет неправильным? Я так не думаю. - person Antonio; 27.05.2016
comment
Да, конечно. У меня сейчас нет кода OpenCV в руке. а поиск части кода в Интернете затруднен. см. сейчас stackoverflow.com/a/32663709/4523099 Я постараюсь привести некоторые четкие ссылки для моей заметки позже. - person Humam Helfawi; 27.05.2016
comment
Большое спасибо за указание на это! Я провел небольшое исследование и опубликовал свои результаты в качестве дополнительного ответа здесь. Я думаю, ваш ответ мог бы быть немного более точным: это правда, что нельзя использовать uint16_t, но неясно, что на самом деле следует использовать (вероятно, unsigned short было бы хорошо, но в этот момент я бы предпочел подход, упомянутый в моем отвечать). - person Antonio; 27.05.2016
comment
один из хороших способов итерации - а еще лучше - не повторять вообще, если вы можете помочь, а использовать матричные выражения или существующие функции OpenCV. Например. в этом случае выберите ROI, используя _1 _, _ 2_ и друзей, а затем просто назначьте ему скаляр. Это часто приводит к лучшей производительности, поскольку код OpenCV имеет тенденцию быть лучше оптимизированным, чем часто наивные итерации по матрице. - person Dan Mašek; 27.05.2016
comment
В этом нет никаких сомнений. Но когда нет предварительно созданной функции, вы должны сделать это так или даже лучше, используя LUT, если avail или tbb parllel и т. Д. - person Humam Helfawi; 27.05.2016