最近做项目有个模块与图像处理相关的功能,其中有一步要把原图转为灰度图用opencv做的时候发现void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 );这个函数转灰度图有两个问题,1:原图已经是灰度图了,再次调用会崩溃2:如果是8位的bmp图转换也会崩溃,于是查网上资料有自己写算法来转换,后来查QImage帮助文档,QImage有自带的转换函数convertToFormat(QImage::Format_Grayscale8, Qt::AutoColor)
对比两种效果如下:
1:手动算法
QImage QImageToGrayDialog::QImageToGray(QImage image)
{
int height = image.height();
int width = image.width();
QImage grayImage(width, height, QImage::Format_Indexed8);
grayImage.setColorCount(256);
for(int i = 0; i < 256; i++)
{
grayImage.setColor(i, qRgb(i, i, i));
}
qDebug() << "QImageToGrayDialog::QImageToGray====format===" << image.format();
switch(image.format())
{
case QImage::Format_Grayscale8:
case QImage::Format_Indexed8:
for(int i = 0; i < height; i ++)
{
const uchar *pSrc = (uchar *)image.constScanLine(i);
uchar *pDest = (uchar *)grayImage.scanLine(i);
memcpy(pDest, pSrc, width);
}
break;
case QImage::Format_RGB32:
case QImage::Format_ARGB32:
case QImage::Format_ARGB32_Premultiplied:
for(int i = 0; i < height; i ++)
{
const QRgb *pSrc = (QRgb *)image.constScanLine(i);
uchar *pDest = (uchar *)grayImage.scanLine(i);
for( int j = 0; j < width; j ++)
{
pDest[j] = qGray(pSrc[j]);
}
}
break;
default:
break;
}
return grayImage;
}
与原图对比效果:
2:QImage的转灰度API
QPixmap pix2 = QPixmap::fromImage(image.convertToFormat(QImage::Format_Grayscale8, Qt::AutoColor));
pix2 = pix2.scaled(400, 300);
ui->label_1->setPixmap(pix1);
原图,手动算法转换图,QImage API转换图三者对比:
bool isLoad = image.load(":/image/t2.jpg");
if(isLoad)
{
QPixmap pixOrg = QPixmap::fromImage(image);
pixOrg = pixOrg.scaled(400, 300);
ui->label->setPixmap(pixOrg);
QImage grayImage = QImageToGray(image);
QPixmap pix1 = QPixmap::fromImage(grayImage);
pix1 = pix1.scaled(400, 300);
QPixmap pix2 = QPixmap::fromImage(image.convertToFormat(QImage::Format_Grayscale8, Qt::AutoColor));
pix2 = pix2.scaled(400, 300);
ui->label_1->setPixmap(pix1);
ui->label_2->setPixmap(pix2);
}
对比结果:
![](https://i-blog.csdnimg.cn/blog_migrate/d030baa207d3bb8db684845f401239a2.png)
如果原图本身就是灰度图呢,对比如下:
![](https://i-blog.csdnimg.cn/blog_migrate/ee8d64d0d2946d0bb38a392d6bb338e5.png)
如果原图是8位深度的bmp图片,对比如下:
![](https://i-blog.csdnimg.cn/blog_migrate/5c85b66a501b45b86acab6886c156976.png)
这个效果就很明显了,QImage的API转换比手写的算法效果要好很多
完整的代码如下:
#ifndef QIMAGETOGRAYDIALOG_H
#define QIMAGETOGRAYDIALOG_H
#include <QDialog>
QT_BEGIN_NAMESPACE
namespace Ui { class QImageToGrayDialog; }
QT_END_NAMESPACE
class QImageToGrayDialog : public QDialog
{
Q_OBJECT
public:
QImageToGrayDialog(QWidget *parent = nullptr);
~QImageToGrayDialog();
void initView();
QImage QImageToGray(QImage image);
public slots:
void slotQImageToGray();
private:
Ui::QImageToGrayDialog *ui;
};
#endif // QIMAGETOGRAYDIALOG_H
#include "qimagetograydialog.h"
#include "ui_qimagetograydialog.h"
#include <QDebug>
#include <QImage>
#include <QPixmap>
QImageToGrayDialog::QImageToGrayDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::QImageToGrayDialog)
{
ui->setupUi(this);
initView();
}
QImageToGrayDialog::~QImageToGrayDialog()
{
delete ui;
}
void QImageToGrayDialog::initView()
{
connect(ui->btnQImageToGray, SIGNAL(clicked()), this, SLOT(slotQImageToGray()));
}
QImage QImageToGrayDialog::QImageToGray(QImage image)
{
int height = image.height();
int width = image.width();
QImage grayImage(width, height, QImage::Format_Indexed8);
grayImage.setColorCount(256);
for(int i = 0; i < 256; i++)
{
grayImage.setColor(i, qRgb(i, i, i));
}
qDebug() << "QImageToGrayDialog::QImageToGray====format===" << image.format();
switch(image.format())
{
case QImage::Format_Grayscale8:
case QImage::Format_Indexed8:
for(int i = 0; i < height; i ++)
{
const uchar *pSrc = (uchar *)image.constScanLine(i);
uchar *pDest = (uchar *)grayImage.scanLine(i);
memcpy(pDest, pSrc, width);
}
break;
case QImage::Format_RGB32:
case QImage::Format_ARGB32:
case QImage::Format_ARGB32_Premultiplied:
for(int i = 0; i < height; i ++)
{
const QRgb *pSrc = (QRgb *)image.constScanLine(i);
uchar *pDest = (uchar *)grayImage.scanLine(i);
for( int j = 0; j < width; j ++)
{
pDest[j] = qGray(pSrc[j]);
}
}
break;
default:
break;
}
return grayImage;
}
void QImageToGrayDialog::slotQImageToGray()
{
QImage image;
//bool isLoad = image.load(":/image/aa.png");
//bool isLoad = image.load(":/image/gray.png");
bool isLoad = image.load(":/image/min8bit.bmp");
//bool isLoad = image.load(":/image/big.jpg");
//bool isLoad = image.load(":/image/t3.jpg");
//bool isLoad = image.load(":/image/t2.jpg");
//bool isLoad = image.load(":/image/gray_1.png");
if(isLoad)
{
QPixmap pixOrg = QPixmap::fromImage(image);
pixOrg = pixOrg.scaled(400, 300);
ui->label->setPixmap(pixOrg);
QImage grayImage = QImageToGray(image);
QPixmap pix1 = QPixmap::fromImage(grayImage);
pix1 = pix1.scaled(400, 300);
QPixmap pix2 = QPixmap::fromImage(image.convertToFormat(QImage::Format_Grayscale8, Qt::AutoColor));
pix2 = pix2.scaled(400, 300);
ui->label_1->setPixmap(pix1);
ui->label_2->setPixmap(pix2);
}
}
参考: