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:
How to fix that?
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.
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 toQPainter
.– Kuba Ober
Sep 14 '18 at 14:31