我需要比较两个彩色 RBG 图像并获得逐像素差异的结果图像。有什么想法我可以在 qt 中做到这一点吗?
如果您有任何帮助或建议,我将不胜感激。
这是基于此 QtForum 问题的替代方案:
void substract(const QImage &left, const QImage &rigth, QImage &result)
{
int w=min(left.width(), rigth.width());
int h=min(left.height(),rigth.height();
w=min(w, result.width());
h=min(h, result.height();
//<-This ensures that you work only at the intersection of images areas
for(int i=0;i<h;i++){
QRgb *rgbLeft=(QRgb*)left.constScanLine(i);
QRgb *rgbRigth=(QRgb*)rigth.constScanLine(i);
QRgb *rgbResult=(QRgb*)result.constScanLine(i);
for(int j=0;j<w;j++){
rgbResult[j] = rgbLeft[j]-rgbRigth[j];
}
}
}
首先,RGB 图像是包含 3 个通道 (R,G,B) 的 3 维矩阵
要实现差异,您只需将矩阵相减即可。
如果您使用 OpenCv,请考虑下面的代码,否则您可以遍历矩阵并分别减去每个位置。
#include <cv.h>
#include <highgui.h>
using namespace cv;
Mat img = imread("...");
Mat img2 = imread("...");
Mat diff_img = img - img2;
使用
QImage
,您可以在像素级别进行迭代,并简单地将 RBG 差异输出到第三个图像中。
QRgb QImage::pixel(int x, int y) const
void QImage::setPixelColor(int x, int y, const QColor &color)
请记住按顺序迭代行以获得最佳性能。这意味着该行应该是您的内部循环。很多时候,人们本能地做相反的事情,可能是因为大多数人优先考虑宽度而不是高度,因此将行作为外循环。
这是比较两个相同尺寸(高度和宽度)图像的方法。您还可以使用一些 STD 功能来代替这个简单的代码。这只是为了展示它应该如何进行
// 'first' and 'second' it's QImage objects
int AbsoluteError = 0;
for (int y = 0; y < first.height(); ++y)
{
QRgb *line1 = reinterpret_cast<QRgb*>(first.scanLine(y));
QRgb *line2 = reinterpret_cast<QRgb*>(second.scanLine(y));
for (int x = 0; x < first.width(); ++x)
{
QRgb &rgb1 = line1[x];
int A1 = qAlpha(rgb1);
int R1 = qRed(rgb1);
int G1 = qGreen(rgb1);
int B1 = qBlue(rgb1);
QRgb &rgb2 = line2[x];
int A2 = qAlpha(rgb2);
int R2 = qRed(rgb2);
int G2 = qGreen(rgb2);
int B2 = qBlue(rgb2);
bool A = A1 == A2;
bool R = R1 == R2;
bool G = G1 == G2;
bool B = B1 == B2;
if(!A || !R || !G || !B)
{
rgb2 = qRgba(qRed(rgb2), qGreen(0), qBlue(rgb2), qAlpha(rgb2));
++AbsoluteError;
}
}
}
ui->LineEdit1->setText(QString::number(AbsoluteError));
ui->LineEdit2->setText(QString::number((AbsoluteError*100)/(width1*height1))); //absolute error in %
bool ImagesAreSimilar(QImage *img1,QImage *img2) {
if (img1->isNull()||img2->isNull())
{
return false ;
}
if (img1->height()!=img2->height()) {
return false ;
}
if (img1->width()!=img2->width()) {
return false ;
}
auto pixel1 = img1->bits();
auto pixel2 = img2->bits();
bool similar=true;
for (int y = 0; y < img1->height(); y++)
{
for (int x = 0; x < img1->width(); x++)
{
if ( (pixel1[0]!=pixel2[0])||
(pixel1[1]!=pixel2[1])||
(pixel1[2]!=pixel2[2])||
(pixel1[3]!=pixel2[3])) {
return false ;
}
pixel1 += 4;
pixel2 += 4;
}
}
返回相似;
}