我正在尝试创建一个应用程序,我正在尝试集成opencv和qt。
我成功地使用以下代码将cv :: Mat转换为QImage:
void MainWindow::loadFile(const QString &fileName)
{
cv::Mat tmpImage = cv::imread(fileName.toAscii().data());
cv::Mat image;
if(!tmpImage.data || tmpImage.empty())
{
QMessageBox::warning(this, tr("Error Occured"), tr("Problem loading file"), QMessageBox::Ok);
return;
}
/* Mat to Qimage */
cv::cvtColor(tmpImage, image, CV_BGR2RGB);
img = QImage((const unsigned char*)(image.data), image.cols, image.rows, QImage::Format_RGB888);
imgLabel->setPixmap(QPixmap::fromImage(img));
imgLabel->resize(imgLabel->pixmap()->size());
saveAsAct->setEnabled(true);
}
但是,当我尝试使用以下代码将QImage转换为cv :: Mat时:
bool MainWindow::saveAs()
{
if(fileName.isEmpty())
{
QMessageBox::warning(this, tr("Error Occured"), tr("Problem loading file"), QMessageBox::Close);
return EXIT_FAILURE;
}else{
outputFileName = QFileDialog::getSaveFileName(this, tr("Save As"), fileName.toAscii().data(), tr("Image Files (*.png *.jpg *.jpeg *.bmp)\n *.png\n *.jpg\n *.jpeg\n *.bmp"));
/* Qimage to Mat */
cv::Mat mat = cv::Mat(img.height(), img.width(), CV_8UC4, (uchar*)img.bits(), img.bytesPerLine());
cv::Mat mat2 = cv::Mat(mat.rows, mat.cols, CV_8UC3 );
int from_to[] = {0,0, 1,1, 2,2};
cv::mixChannels(&mat, 1, &mat2, 1, from_to, 3);
cv::imwrite(outputFileName.toAscii().data(), mat);
}
saveAct->setEnabled(true);
return EXIT_SUCCESS;
}
我没有成功,结果是图像完全混乱。在我搜索的网中,我看到人们正在使用这种方式而没有提到任何具体问题。有人有任何想法,关于可能导致问题的原因是什么?提前谢谢。
Theoodore
P.S。我在使用gnome-3.4
的Arch Linux系统下使用opencv 2.4和Qt 4.8答案 0 :(得分:2)
找出"正确"解决复制(不参考)QImage到cv :: Mat
Martin Beckett的答案几乎是正确的
for (int i=0;i<image.height();i++) {
memcpy(mat.ptr(i),image.scanline(i),image.bytesperline());
}
我没有看到完整的代码,但我想您可能想要这样使用它
cv::Mat mat(image.height(), image.width(), CV_8UC3);
for (int i=0;i<image.height();i++) {
memcpy(mat.ptr(i),image.scanline(i),image.bytesperline());
}
但这段代码存在问题, 由cv :: Mat 分配的内存可能不会具有相同的&#34; bytesperline&#34;作为QImage
我找到的解决方案是首先引用QImage,然后克隆它
return cv::Mat(img.height(), img.width(), format, img.bits(), img.bytesPerLine()).clone();
Martin Beckett建议的解决方案可以在大多数情况下产生正确的结果 在我碰到它的时候,我没有注意到有一个bug。
无论如何,我希望这是一个正确的&#34;解。如果您发现任何错误,请告知 每个人都知道,所以我们可以改变以改进代码。
答案 1 :(得分:0)
opencv图像是步进的,因此每行开始于32位的倍数,这使得内存访问更快。如果您使用的是3字节/像素格式,那么除非您的宽度是4的倍数的1/3,否则每行末尾都会有“备用”内存
安全的方法是一次复制一行图像数据。 opencv mat.ptr(row)返回指向每行开头的指针,QImage .scanline(row)成员执行相同的操作
请参阅How to output this 24 bit image in Qt
编辑:像
这样的东西for (int i=0;i<image.height();i++) {
memcpy(mat.ptr(i),image.scanline(i),image.bytesperline());
}
答案 2 :(得分:0)
我想你可能会觉得这很有用。 http://www.jdxyw.com/?p=1480
它使用IplImage来获取数据,但是您可以使用cv :: Mat和Mat.data来获取指向原始矩阵的指针。我希望你会觉得这很有用。
答案 3 :(得分:0)
QImage MatToQImage(const Mat& mat)
{
// 8-bits unsigned, NO. OF CHANNELS=1
if(mat.type()==CV_8UC1)
{
// Set the color table (used to translate colour indexes to qRgb values)
QVector<QRgb> colorTable;
for (int i=0; i<256; i++)
colorTable.push_back(qRgb(i,i,i));
// Copy input Mat
const uchar *qImageBuffer = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage img(qImageBuffer, mat.cols, mat.rows, mat.step, QImage::Format_Indexed8);
img.setColorTable(colorTable);
return img;
}
// 8-bits unsigned, NO. OF CHANNELS=3
if(mat.type()==CV_8UC3)
{
// Copy input Mat
const uchar *qImageBuffer = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage img(qImageBuffer, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
return img.rgbSwapped();
}
else
{
qDebug() << "ERROR: Mat could not be converted to QImage.";
return QImage();
}
} // MatToQImage()
答案 4 :(得分:0)
这是我从here thanks to jose.得到的东西。它帮助我克服了这一点。
要在Qt(QImage)中显示OpenCV图像(cv :: Mat),您必须按照以下步骤操作:
cv::cvtColor(imageBGR, imageRGB, CV_BGR2RGB);
QImage qImage((uchar*) imageRGB.data, imageRGB.cols, imageRGB.rows, imageRGB.step, QImage::Format_RGB888);
请注意使用QImage :: Format。阅读有关此问题的Qt。
答案 5 :(得分:0)
如果您仍在寻找解决方案。这是一个:
Cv :: Mat to QImage:
QImage Mat2QImage(cv::Mat &image )
{
QImage qtImg;
if( !image.empty() && image.depth() == CV_8U ){
if(image.channels() == 1){
qtImg = QImage( (const unsigned char *)(image.data),
image.cols,
image.rows,
QImage::Format_Indexed8 );
}
else{
cvtColor( image, image, CV_BGR2RGB );
qtImg = QImage( (const unsigned char *)(image.data),
image.cols,
image.rows,
QImage::Format_RGB888 );
}
}
return qtImg;
}
对于cv :: Mat的QImage。
cv::Mat QImage2Mat(QImage &image) {
cv::Mat cvImage;
switch (image.format()){
case QImage::Format_RGB888:{
cvImage = cv::Mat(image.height(),
image.width(),
CV_8UC3,
image.bits(),
image.bytesPerLine());
cv::cvtColor(cvImage, cvImage, CV_RGB2BGR);
return cvImage;
}
case QImage::Format_Indexed8:{
cvImage = cv::Mat(image.height(),
image.width(),
CV_8U,
image.bits(),
image.bytesPerLine());
return cvImage;
}
default:
break;
}
return cvImage;
}