将QImage转换为灰度

sas*_*alm 8 c++ qt grayscale qimage

我有一个QImage,我需要将其转换为灰度,然后用颜色绘制它.我发现了一个allGray()isGrayScale()函数检查图像已经灰度,但没有toGrayScale()或类似命名的功能.

现在我正在使用这段代码,但它没有很好的性能:

for (int ii = 0; ii < image.width(); ii++) {
    for (int jj = 0; jj < image.height(); jj++) {
        int gray = qGray(image.pixel(ii, jj));
        image.setPixel(ii, jj, QColor(gray, gray, gray).rgb());
    }
}
Run Code Online (Sandbox Code Playgroud)

将QImage转换为灰度的最佳方法是什么?

UmN*_*obe 10

而不是使用较慢的功能 QImage::pixelQImage::setPixel使用 QImage::scanline访问数据.扫描(水平线)上的像素是连续的.假设您有32 bpp图像,则可以使用QRgb迭代扫描.最后总是将x坐标放在内部循环中.这使 :

for (int ii = 0; ii < image.height(); ii++) {
    uchar* scan = image.scanLine(ii);
    int depth =4;
    for (int jj = 0; jj < image.width(); jj++) {

        QRgb* rgbpixel = reinterpret_cast<QRgb*>(scan + jj*depth);
        int gray = qGray(*rgbpixel);
        *rgbpixel = QColor(gray, gray, gray).rgba();
    }
}
Run Code Online (Sandbox Code Playgroud)

使用3585 x 2386图像进行快速测试

********* Start testing of TestImage *********
Config: Using QTest library 4.7.4, Qt 4.7.4
PASS   : TestImage::initTestCase()

RESULT : TestImage::grayscaleOp():
     390 msecs per iteration (total: 390, iterations: 1)
PASS   : TestImage::grayscaleOp()

RESULT : TestImage::grayscaleFast():
     125 msecs per iteration (total: 125, iterations: 1)
PASS   : TestImage::grayscaleFast()

PASS   : TestImage::cleanupTestCase()
Totals: 4 passed, 0 failed, 0 skipped
********* Finished testing of TestImage *********
Run Code Online (Sandbox Code Playgroud)

源代码: testimage.h文件:

#ifndef TESTIMAGE_H
#define TESTIMAGE_H

#include <QtTest/QtTest>

#include <QObject>
#include <QImage>

class TestImage : public QObject
{
    Q_OBJECT
public:
    explicit TestImage(QObject *parent = 0);

signals:

private slots:
    void grayscaleOp();

    void grayscaleFast();

private:
    QImage imgop;
    QImage imgfast;
};

#endif // TESTIMAGE_H
Run Code Online (Sandbox Code Playgroud)

testimage.cpp文件:

#include "testimage.h"

TestImage::TestImage(QObject *parent)
    : QObject(parent)
    , imgop("path_to_test_image.png")
    , imgfast("path_to_test_image.png")
{
}


void TestImage::grayscaleOp()
{
    QBENCHMARK
    {
        QImage& image = imgop;

        for (int ii = 0; ii < image.width(); ii++) {
            for (int jj = 0; jj < image.height(); jj++) {
                int gray = qGray(image.pixel(ii, jj));
                image.setPixel(ii, jj, QColor(gray, gray, gray).rgb());
            }
        }
    }
}

void TestImage::grayscaleFast()
{

    QBENCHMARK {

    QImage& image = imgfast;


    for (int ii = 0; ii < image.height(); ii++) {
        uchar* scan = image.scanLine(ii);
        int depth =4;
        for (int jj = 0; jj < image.width(); jj++) {

            QRgb* rgbpixel = reinterpret_cast<QRgb*>(scan + jj*depth);
            int gray = qGray(*rgbpixel);
            *rgbpixel = QColor(gray, gray, gray).rgba();
        }
    }

    }
}

QTEST_MAIN(TestImage)
Run Code Online (Sandbox Code Playgroud)

专业档案:

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = QImageTest
TEMPLATE = app

CONFIG  += qtestlib

SOURCES += testimage.cpp

HEADERS += testimage.h
Run Code Online (Sandbox Code Playgroud)

重要的提示:

  • 通过反转循环,您已经获得了重要的性能提升.在这个测试案例中它是~90ms.
  • 您可以使用其他库(如opencv)进行灰度转换,然后从opencv缓冲区构建Qimage.我期待更好的性能提升.


小智 9

从Qt 5.5开始,您可以调用QImage :: convertToFormat()将QImage转换为灰度,如下所示:

QImage image = ...;
image.convertToFormat(QImage::Format_Grayscale8);
Run Code Online (Sandbox Code Playgroud)