How to translate/crop a QImage with subpixel accuracy?

How to translate/crop a QImage with subpixel accuracy?



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?






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 Ober
Sep 14 '18 at 14:31


QPainter


QImage::transformed


QPainter






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 7:30





1 Answer
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;



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)