3

The use case is a 2D map with a vehicle at the origin. The map shall also be translated in case the vehicle moves e.g. 0.5 pixels. I believe this should be feasible using bilinear interpolation or similar.

If there is no simple solution using Qt, I would appreciate hints to non-Qt-solutions.

Minimal example:

#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();
}

Given an input image with a sharp border (see below), I would expect the output image to have a blurred border. This is not the case:

enter image description here

How to fix that?

scopchanov
  • 7,966
  • 10
  • 40
  • 68
gebbissimo
  • 2,137
  • 2
  • 25
  • 35
  • 2
    `QPainter` can draw images at floating point coordinates. In an anti-aliased painter, won't that do what you need? `QImage::transformed` perhaps does less than the raster backend to `QPainter`. – Kuba hasn't forgotten Monica Sep 14 '18 at 14:31
  • I will give it a try, thanks for your answer. While I knew of QPainter, I thought it can be only used to draw lines and polygons, not QImages as well. – gebbissimo Sep 14 '18 at 14:55
  • I tried it using the function "void QPainter::drawImage(const QPointF &point, const QImage &image)". However, no success, it seems to round the floating point numbers before drawing. Would you have any other ideas, @KubaOber? P.s.: Converting the image to be drawn to QPixmap and using drawPixmap has the same result – gebbissimo Sep 17 '18 at 07:30

1 Answers1

1

I tested openCV and its function cv::warpAffine allows translation with sub-pixel precision (see MWE below).

After founding some old, unanswered threads on qtcentre.org, it seems to me that Qt simply does not allow translation with sub-pixel precision. Please correct me if I am wrong.

For Qt, I only found workarounds to scale the image first, translate with pixel accuracy and scale down again. Unfortunately, this approach is too computationally expensive for my use case.

MWE with opencv:

#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;
}
gebbissimo
  • 2,137
  • 2
  • 25
  • 35