Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将图像转换为灰度_C++_Qt_Grayscale_Qimage - Fatal编程技术网

C++ 将图像转换为灰度

C++ 将图像转换为灰度,c++,qt,grayscale,qimage,C++,Qt,Grayscale,Qimage,我有一个QImage,我需要把它转换成灰度,然后在上面画上颜色。我找到了一个allGray()和isGrayScale()函数来检查图像是否已经是灰度的,但是没有toGrayScale()或类似的命名函数 QImage convertToGrayScale(const QImage &srcImage) { // Convert to 32bit pixel format QImage dstImage = srcImage.convertToFormat(srcIm

我有一个QImage,我需要把它转换成灰度,然后在上面画上颜色。我找到了一个
allGray()
isGrayScale()
函数来检查图像是否已经是灰度的,但是没有
toGrayScale()
或类似的命名函数

QImage convertToGrayScale(const QImage &srcImage) {
     // Convert to 32bit pixel format
     QImage dstImage = srcImage.convertToFormat(srcImage.hasAlphaChannel() ?
              QImage::Format_ARGB32 : QImage::Format_RGB32);

     unsigned int *data = (unsigned int*)dstImage.bits();
     int pixelCount = dstImage.width() * dstImage.height();

     // Convert each pixel to grayscale
     for(int i = 0; i < pixelCount; ++i) {
        int val = qGray(*data);
        *data = qRgba(val, val, val, qAlpha(*data));
        ++data;
     }

     return dstImage;
  }
现在我正在使用这段代码,但它的性能不是很好:

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());
    }
}
for(int ii=0;ii
在性能方面,将QImage转换为灰度的最佳方法是什么?

使用
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();
    }
}
源代码: 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
重要提示:

  • 通过反转循环,您已经获得了重要的性能提升。在这个测试用例中,它是
    ~90ms
  • 您可以使用其他库(如opencv)进行灰度转换,然后从opencv缓冲区构建Qimage。我期待着更好的性能改进
我将发布@UmNyobe代码的一个稍加修改的版本。我只是为扫描线增加一个指针,而不是通过索引计算每个像素

// We assume the format to be RGB32!!!
Q_ASSERT(image.format() == QImage::Format_RGB32);
for (int ii = 0; ii < image.height(); ii++) {
    QRgb *pixel = reinterpret_cast<QRgb*>(image.scanLine(ii));
    QRgb *end = pixel + image.width();
    for (; pixel != end; pixel++) {
        int gray = qGray(*pixel);
        *pixel = QColor(gray, gray, gray).rgb();
    }
}
//我们假设格式为RGB32!!!
Q_断言(image.format()==QImage::format_RGB32);
对于(int ii=0;ii
内部qt类
QPixmapColorizeFilter
使用函数
grayscale
解决类似问题

我从中导出了以下函数,应该可以解决这个问题

重要的部分是将图像转换成32位格式,这样你就可以把每个像素看作32位的值,而不需要关心位对齐。 您还可以直接使用

bits
函数,在所有像素上迭代,而不是在行和列上迭代。使用此技巧可以避免在
scanLine
函数中执行乘法

QImage convertToGrayScale(const QImage &srcImage) {
     // Convert to 32bit pixel format
     QImage dstImage = srcImage.convertToFormat(srcImage.hasAlphaChannel() ?
              QImage::Format_ARGB32 : QImage::Format_RGB32);

     unsigned int *data = (unsigned int*)dstImage.bits();
     int pixelCount = dstImage.width() * dstImage.height();

     // Convert each pixel to grayscale
     for(int i = 0; i < pixelCount; ++i) {
        int val = qGray(*data);
        *data = qRgba(val, val, val, qAlpha(*data));
        ++data;
     }

     return dstImage;
  }
QImage convertToGrayScale(常量QImage&srcImage){
//转换为32位像素格式
QImage dstImage=srcImage.convertToFormat(srcImage.hasAlphaChannel()?
QImage::Format_ARGB32:QImage::Format_RGB32);
unsigned int*数据=(unsigned int*)dstmimage.bits();
int pixelCount=dstImage.width()*dstImage.height();
//将每个像素转换为灰度
对于(int i=0;i
自Qt 5.5以来,您可以调用将QImage转换为灰度,如下所示:

QImage image = ...;
image.convertToFormat(QImage::Format_Grayscale8);

虽然这仍然不是最好的方法,但是尝试切换for循环(因此首先迭代ii,然后迭代jj)。根据内存布局的不同,这可能会导致更好的缓存一致性,并使代码更快。@Daerst是的,这是一个很好的建议,但如果我找到了更好的解决方案,优化解决方案就没有意义了。如果没有其他解决方案,那么当保证两行之间有连续像素时,.bits可能会起作用。我用扫描线来比较保守。例如,使用
QImage::QImage(uchar*data,int-width,int-height,int-bytesPerLine,Format-Format)
创建的图像可能具有
bytesPerLine>width*sizeofpixel()
。这应该是公认的答案。为我工作-谢谢:)
QImage convertToGrayScale(const QImage &srcImage) {
     // Convert to 32bit pixel format
     QImage dstImage = srcImage.convertToFormat(srcImage.hasAlphaChannel() ?
              QImage::Format_ARGB32 : QImage::Format_RGB32);

     unsigned int *data = (unsigned int*)dstImage.bits();
     int pixelCount = dstImage.width() * dstImage.height();

     // Convert each pixel to grayscale
     for(int i = 0; i < pixelCount; ++i) {
        int val = qGray(*data);
        *data = qRgba(val, val, val, qAlpha(*data));
        ++data;
     }

     return dstImage;
  }
QImage image = ...;
image.convertToFormat(QImage::Format_Grayscale8);