Как конвертировать ROI из/в QImage в/из cv::Mat?

Я не могу правильно преобразовать и/или отобразить ROI с помощью QRect в QImage и создать изображение cv::Mat из QImage. Проблема симметрична, т.е. я не могу правильно получить ROI, используя cv::Rect в cv::Mat и создавая QImage из Mat. Удивительно, но все работает нормально, когда ширина и высота cv::Rect или QRect равны.

В дальнейшем моим полноразмерным изображением будет cv::Mat matImage. Он имеет тип CV_8U и размер квадрата 2048x2048.

int x = 614;
int y = 1156;

// buggy
int width = 234;
int height = 278;

//working
//    int width = 400;
//    int height = 400;
QRect ROI(x, y, width, height);

QImage imageInit(matImage.data, matImage.cols, matImage.rows,   QImage::Format_Grayscale8);
QImage imageROI = imageInit.copy(ROI);
createNewImage(imageROI);

unsigned char* dataBuffer = imageROI.bits();
cv::Mat tempImage(cv::Size(imageROI.width(), imageROI.height()), CV_8UC1, dataBuffer, cv::Mat::AUTO_STEP);

cv::namedWindow( "openCV imshow() from a cv::Mat image", cv::WINDOW_AUTOSIZE );
cv::imshow( "openCV imshow() from a cv::Mat image", tempImage);  

The screenshot below illustrates the issue.

полный размер и рентабельность инвестиций (слева) Полноразмерный cv::Mat matImage. (В центре) ожидаемый результат от QImage и QRect (что примерно соответствует зеленому прямоугольнику, нарисованному от руки). (Справа) испорченный результат cv::Mat matImageROI


person Wall-E    schedule 08.04.2016    source источник
comment
Я использую Qt 5.6 и openCV 3.1, Mac OS X 10.10.5, Macbook Pro Retina.   -  person Wall-E    schedule 08.04.2016


Ответы (1)


Изучая другие проблемы, связанные с преобразованием между cv::Mat и QImage, кажется, что шаг становится «нестандартным» в некоторых конкретных размерах ROI. Например, из этот пост я обнаружил, что нужно просто изменить cv::Mat::AUTO_STEP на imageROI.bytesPerLine() в cv::Mat tempImage(cv::Size(imageROI.width(), imageROI.height()), CV_8UC1, dataBuffer, cv::Mat::AUTO_STEP);

поэтому вместо этого я получаю: cv::Mat matImageROI(cv::Size(imageROI.width(), imageROI.height()), CV_8UC1, dataBuffer, imageROI.bytesPerLine());

В обратном случае, т. е. при создании QImage из ROI cv::Mat, можно было бы использовать свойство cv::Mat::step.

Например:

QImage imageROI(matImageROI.data, matImageROI.cols, matImageROI.rows, matImageROI.step, QImage::Format_Grayscale8);

вместо:

QImage imageROI(matImageROI.data, matImageROI.cols, matImageROI.rows, QImage::Format_Grayscale8);

Обновить

В случае нечетных размеров ROI, хотя это не проблема при использовании imshow() с cv::Mat или QImage с QGraphicsScene, это становится проблемой при использовании openGL (с QOpenGLWidget). Я предполагаю, что самый простой обходной путь - просто ограничить ROI, чтобы они имели равные размеры.

person Wall-E    schedule 09.04.2016