如何使用亚像素精度来翻译/裁剪 QImage?

3

使用情景是一个带有车辆原点的2D地图。如果车辆移动了0.5像素,地图也应该进行相应的平移。我认为可以使用双线性插值或类似的方法来实现。

如果在Qt中没有简单的解决方案,我会感激非Qt解决方案的提示。

最小示例:

#include <QtWidgets/QApplication>
#include <QtGui/QImage>
#include <QLabel>

int main(int argc, char *argv[])
{

    QApplication app(argc, argv);

    // Parameters
    QString PATH_IMG_IN = "../img_test_rect.jpg";
    QString PATH_IMG_OUT = "../img_out.png";
    float TRANSLATE_IN_PX = 0.5;

    // load image
    QImage img;
    img.load(PATH_IMG_IN);

    // rotate image.
    QTransform trans;
    trans.translate(0,TRANSLATE_IN_PX);
    QImage img_new = img.transformed(trans, Qt::SmoothTransformation);

    // save image
    img_new.save(PATH_IMG_OUT, nullptr, 100);

    // optional: Get info about true transformation matrix
    QTransform trans_true = QImage::trueMatrix(trans, img.width(), img.height());

    return app.exec();
}

给定一个具有锐利边界的输入图像(见下文),我期望输出图像具有模糊的边界。但事实并非如此:

enter image description here

如何解决这个问题?


2
QPainter可以在浮点坐标处绘制图像。在抗锯齿绘图器中,这样做是否符合您的需求?QImage::transformed可能比QPainter的光栅后端功能更少。 - Kuba hasn't forgotten Monica
我会尝试一下,谢谢你的回答。虽然我知道QPainter,但我认为它只能用于绘制线条和多边形,而不是QImages。 - gebbissimo
我尝试使用函数“void QPainter::drawImage(const QPointF &point, const QImage &image)”进行绘制,但是没有成功,似乎在绘制之前会将浮点数四舍五入。@KubaOber,你有其他的想法吗?附:将要绘制的图像转换为QPixmap并使用drawPixmap也会产生相同的结果。 - gebbissimo
1个回答

1

我测试了openCV,它的函数cv::warpAffine允许使用亚像素精度进行平移(见下面的MWE)。

在qtcentre.org上发现一些未被回答的旧帖子后,我觉得Qt似乎不允许使用亚像素精度进行平移。如果我错了,请纠正我。

对于Qt,我只找到了先缩放图像,然后以像素精度平移并再次缩小的解决方法。不幸的是,这种方法对我的用例来说计算开销太大。

使用opencv的MWE:

#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"

int main(int argc, char** argv) {

// parameters
std::string PATH_IMG_IN = "../img_test_rect.jpg";
std::string PATH_IMG_OUT = "../img_out.jpg";

// load image
cv::Mat img = cv::imread(PATH_IMG_IN, CV_LOAD_IMAGE_GRAYSCALE);
if (!img.data)                              // Check for invalid input
{
    std::cout << "Could not open or find the image" << std::endl;
    return -1;
}

// rotate image
cv::Mat img_new = cv::Mat::ones(img.size(), img.type()) * 0.5; // another type = CV_8U
cv::Mat mat_transform = (cv::Mat_<float>(2, 3) << 1, 0, 0.5, 0, 1, 0);
cv::warpAffine(img, img_new, mat_transform, img_new.size());

// show image
cv::imshow("Display window", img_new);

// save image
cv::imwrite(PATH_IMG_OUT, img_new);

// wait for the user to press any key:
cv::waitKey(0);

return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接