как преобразовать opencv cv :: Mat в qimage

Мне интересно, как бы преобразовать стандартный тип cv :: Mat OpenCV C ++ в Qimage. Я искал вокруг, но мне не повезло. Я нашел код, который преобразует IPlimage в Qimage, но это не то, что я хочу. благодаря

Ответ Михала Коттмана действителен и дает ожидаемый результат для некоторых изображений, но в некоторых случаях он будет терпеть неудачу. Вот решение, которое я нашел для этой проблемы.

QImage imgIn= QImage((uchar*) img.data, img.cols, img.rows, img.step, QImage::Format_RGB888); 

Разница заключается в добавлении части img.step. qt не будет жаловаться без него, но некоторые изображения не будут отображаться должным образом без него. Надеюсь, это поможет.

Вот код для 24-битной RGB и полутоновой шкалы с плавающей запятой. Легко настраивается для других типов. Это так же эффективно, как и получается.

 QImage Mat2QImage(const cv::Mat3b &src) { QImage dest(src.cols, src.rows, QImage::Format_ARGB32); for (int y = 0; y < src.rows; ++y) { const cv::Vec3b *srcrow = src[y]; QRgb *destrow = (QRgb*)dest.scanLine(y); for (int x = 0; x < src.cols; ++x) { destrow[x] = qRgba(srcrow[x][2], srcrow[x][1], srcrow[x][0], 255); } } return dest; } QImage Mat2QImage(const cv::Mat_ &src) { double scale = 255.0; QImage dest(src.cols, src.rows, QImage::Format_ARGB32); for (int y = 0; y < src.rows; ++y) { const double *srcrow = src[y]; QRgb *destrow = (QRgb*)dest.scanLine(y); for (int x = 0; x < src.cols; ++x) { unsigned int color = srcrow[x] * scale; destrow[x] = qRgba(color, color, color, 255); } } return dest; } 

Чтобы преобразовать из cv::Mat в QImage , вы можете попытаться использовать конструктор QImage(uchar * data, int width, int height, Format format) следующим образом ( matcv::Mat ):

 QImage img((uchar*)mat.data, mat.cols, mat.rows, QImage::Format_RGB32); 

Это более эффективно, чем ручное преобразование пикселей в QImage , но вы должны сохранить исходное изображение cv::Mat в памяти. Его можно легко преобразовать в QPixmap и отобразить с помощью QLabel :

 QPixmap pixmap = QPixmap::fromImage(img); myLabel.setPixmap(pixmap); 

Обновить

Поскольку OpenCV по умолчанию использует BGR-порядок, вы должны сначала использовать cvtColor(src, dst, CV_BGR2RGB) чтобы получить макет изображения, который понимает Qt.

Обновление 2:

Если изображение, которое вы пытаетесь показать, имеет нестандартный шаг (когда он не является непрерывным, подmatrix), изображение может выглядеть искаженным. В этом случае лучше явно указать шаг, используя cv::Mat::step1() :

 QImage img((uchar*)mat.data, mat.cols, mat.rows, mat.step1(), QImage::Format_RGB32); 
  Mat opencv_image = imread("fruits.jpg", CV_LOAD_IMAGE_COLOR); Mat dest; cvtColor(opencv_image, dest,CV_BGR2RGB); QImage image((uchar*)dest.data, dest.cols, dest.rows,QImage::Format_RGB888); 

Это то, что сработало для меня. Я изменил код Михала Коттмана выше.

cv :: Mat имеет оператор преобразования в IplImage, поэтому, если у вас есть что-то, что преобразует IplImage в QImage, просто используйте это (или сделайте, возможно, небольшие корректировки, чтобы взять cv :: Mat напрямую, макет памяти – это То же самое, это «просто» заголовок, который отличается.)

У меня такая же проблема, как и у вас, поэтому я разработал четыре функции, чтобы облегчить мою боль, они

 QImage mat_to_qimage_cpy(cv::Mat const &mat, bool swap = true); QImage mat_to_qimage_ref(cv::Mat &mat, bool swap = true); cv::Mat qimage_to_mat_cpy(QImage const &img, bool swap = true); cv::Mat qimage_to_mat_ref(QImage &img, bool swap = true); 

Эти функции могут обрабатывать изображения с 1, 3, 4 каналами, каждый пиксель должен занимать только один байт (CV_8U-> Format_Indexed8, CV_8UC3-> QImage :: Format_RGB888, CV_8UC4-> QImage :: Format_ARGB32), я не занимаюсь другими (QImage :: Format_RGB16, QImage :: Format_RGB666 и т. д.). Коды расположены в github .

Ключевыми понятиями ** transform mat to Qimage ** являются

 /** * @brief copy QImage into cv::Mat */ struct mat_to_qimage_cpy_policy { static QImage start(cv::Mat const &mat, QImage::Format format) { //The fourth parameters--mat.step is crucial, because //opencv may do padding on every row, you need to tell //the qimage how many bytes per row //The last thing is if you want to copy the buffer of cv::Mat //to the qimage, you need to call copy(), else the qimage //will share the buffer of cv::Mat return QImage(mat.data, mat.cols, mat.rows, mat.step, format).copy(); } }; struct mat_to_qimage_ref_policy { static QImage start(cv::Mat &mat, QImage::Format format) { //every thing are same as copy policy, but this one share //the buffer of cv::Mat but not copy return QImage(mat.data, mat.cols, mat.rows, mat.step, format); } }; 

Ключевые понятия преобразования cv::Mat to Qimage :

 /** * @brief copy QImage into cv::Mat */ struct qimage_to_mat_cpy_policy { static cv::Mat start(QImage const &img, int format) { //same as convert mat to qimage, the fifth parameter bytesPerLine() //indicate how many bytes per row //If you want to copy the data you need to call clone(), else QImage //cv::Mat will share the buffer return cv::Mat(img.height(), img.width(), format, const_cast(img.bits()), img.bytesPerLine()).clone(); } }; /** * @brief make Qimage and cv::Mat share the same buffer, the resource * of the cv::Mat must not deleted before the QImage finish * the jobs. */ struct qimage_to_mat_ref_policy { static cv::Mat start(QImage &img, int format) { //same as copy policy, but this one will share the buffer return cv::Mat(img.height(), img.width(), format, img.bits(), img.bytesPerLine()); } }; 

Если было бы хорошо, если кто-то может расширить эти функции и заставить их поддерживать больше типов, пожалуйста, сообщите мне, есть ли какие-либо ошибки.

В этом сообщении показано, как преобразовать QImage в IplImage и vise-versa OpenCV.

После этого, если вам нужна помощь для преобразования между IplImage* в cv::Mat :

 // Assume data is stored by: // IplImage* image; cv::Mat mat(image, true); // Copies the data from image cv::Mat mat(image, false); // Doesn't copy the data! 

Это взлом, но он выполнит свою работу.

Используйте статическую функцию convert16uc1 для изображения глубины:

 QPixmap Viewer::convert16uc1(const cv::Mat& source) { quint16* pSource = (quint16*) source.data; int pixelCounts = source.cols * source.rows; QImage dest(source.cols, source.rows, QImage::Format_RGB32); char* pDest = (char*) dest.bits(); for (int i = 0; i < pixelCounts; i++) { quint8 value = (quint8) ((*(pSource)) >> 8); *(pDest++) = value; // B *(pDest++) = value; // G *(pDest++) = value; // R *(pDest++) = 0; // Alpha pSource++; } return QPixmap::fromImage(dest); } QPixmap Viewer::convert8uc3(const cv::Mat& source) { quint8* pSource = source.data; int pixelCounts = source.cols * source.rows; QImage dest(source.cols, source.rows, QImage::Format_RGB32); char* pDest = (char*) dest.bits(); for (int i = 0; i < pixelCounts; i++) { *(pDest++) = *(pSource+2); // B *(pDest++) = *(pSource+1); // G *(pDest++) = *(pSource+0); // R *(pDest++) = 0; // Alpha pSource+=3; } return QPixmap::fromImage(dest); } QPixmap Viewer::convert16uc3(const cv::Mat& source) { quint16* pSource = (quint16*) source.data; int pixelCounts = source.cols * source.rows; QImage dest(source.cols, source.rows, QImage::Format_RGB32); char* pDest = (char*) dest.bits(); for (int i = 0; i < pixelCounts; i++) { *(pDest++) = *(pSource+2); // B *(pDest++) = *(pSource+1); // G *(pDest++) = *(pSource+0); // R *(pDest++) = 0; // Alpha pSource+=3; } return QPixmap::fromImage(dest); } 

Это помогло мне. Это немного изворотливый, имеет ужасную производительность (как указано в комментариях), но работает со всеми цветовыми форматами, которые я набросал на него до сих пор, и это также очень просто сделать.

Процедура такова:

 cv::Mat image = //...some image you want to display // 1. Save the cv::Mat to some temporary file cv::imwrite("../Images/tmp.jpg",image); // 2. Load the image you just saved as a QImage QImage img; img.load("../Images/tmp.jpg"); 

Готово!

Если вы, скажем, хотите отобразить его в QLabel, продолжайте:

 // Set QImage as content of MyImageQLabel ui-> MyImageQLabel->setPixmap(QPixmap::fromImage(img, Qt::AutoColor)); 

Я лично использую это для простого редактора изображений.

Это может показаться глупым, но сохранение изображения в папку, а затем чтение в объект QImage показалось мне самым быстрым способом.

 Mat x = imread("--.jpg"); imwrite("x.jpg", x); QImage img("x.jpg"); 
  • Показать QImage с QtGui
  • Qt - обновление основного windows со вторым streamом
  • Подключение перегруженных сигналов и слотов в Qt 5
  • Как сделать виджет Qt невидимым без изменения позиции других виджетов Qt?
  • Как сохранить пропорции виджетов в Qt?
  • cv :: Mat to QImage и обратно
  • В шаблоном производном classе, почему мне нужно квалифицировать имена членов базового classа с помощью «this->» внутри функции-члена?
  • Сигнал C ++ для слота QML в Qt
  • Beyond Stack Sampling: C ++ Profilers
  • Как интегрировать OpenCV в проект Android Qt Creator
  • что означает __declspec (dllimport)?
  • Давайте будем гением компьютера.