Qt 彩色图转灰度图

最近做项目有个模块与图像处理相关的功能,其中有一步要把原图转为灰度图用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);
    }
对比结果:
如果原图本身就是灰度图呢,对比如下:
如果原图是8位深度的bmp图片,对比如下:
这个效果就很明显了,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);
    }

}

参考:
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值