Visualization problem to convert a binary image cv::Mat to QImage
I have the following problem when I try to display a binary image with Qt:
First, I have a cv :: Mat binary image (only values 0 and 255). The image represents a structural element.
To deploy on a QLabel in a dialog box, I first convert from cv::Mat to QImage as follows ('aux' is of type cv::Mat and 'vista' is of type QImage):
/* ------------------------------------------- */
QVector< QRgb > colorTable;
for(int i = 0; i < 256; i++)
colorTable.push_back( qRgb(i, i, i) );
const uchar *qImageBuffer = (const uchar*)aux.data; vista = QImage(qImageBuffer, aux.cols, aux.rows, aux.step, QImage::Format_Indexed8); vista.setColorTable( colorTable ); /* ------------------------------------------- */
And then put the QImage on QLabel so:
ui->labelVistaEe->setPixmap( QPixmap::fromImage( vista ) );
ui->labelVistaEe->setScaledContents( true );
However, the image displayed on the QLabel (img_qt.jpg) is not as expected (img_opencv.jpg).
I explain: it is the same binary image which I convert cv::Mat to QImage and then put on a QLabel. However, although the displayed image retains the original shape (a white cross on a black background), the color changes:
Img_opencv.jpg (which is a screenshot of the image cv::Mat deployed directly with OpenCV, ie, without converting to QImage) is a binary image with only two colors: black and white.
Img_qt.jpg (a screenshot of the image that is displayed on the QLabel) is an image showing a cross with various shades of white: white more solid in the center that is degrading gradually as you get to the edges .
My question here, is obviamtente:
(1). What do we owe this effect?... Is this a mistake on my cv::Mat conversion to QImage? or is it a problem of Qt settings? or is it something else?.
(2) How I can solve it?. Keep in mind here, that what I want to display on the QLabel is equal to img_opencv.jpg image.
Thanks in advance for any help and / or suggestions.
Isn't this a case of scaling interpolating between black and white when resizing the label ?
If you change to
ui->labelVistaEe->setScaledContents( false );
Does the image look correct ?
Just a question... If your image is binary, how to you get the shades of gray ?
In my understanding of binary, you only have black or white pixels nothing in between, but I might be missing something here.
Well, that (the fact that it appears gray tones when deploying a binary image) is what I do not understand.
Did I not understand the reason why that is?... That is my question.
Now, to explain more thoroughly:
The binary image I built with OpenCV function called 'getStructuringElement()' that takes three parameters:
structurante element shape (a rectangle, a cross or ellipse), the dimension (rows and columns) and a point (a pair (x, y), does not matter much in this case).
The function returns a Structuring Element (an image cv::Mat) of given dimension and as specified. The structuring element returned is a binary image (0: black, 1: white) where the 1s form an object with the specified shape and 0s are the background (the 0s are just added as filler if necessary to form a rectangular frame, for example, when the SE is a rectangle no pixels 0s).
If invoked getStructuringElement (MORPH_CROSS, Size (3,3), Point (1,1)), you get a picture something like the following:
0 1 0
1 1 1
0 1 0
That is, a binary image 3X3 where foreground pixels form a cross.
All this explanation has little to do with Qt, is only to provide a context. The problem is when I try to deploy the binary image (the structuring element) in a QLabel (of course, first I made a conversion from cv::Mat to QImage).
The images that are attached to clarify this issue more:
The image 'img_opencv.png' is the visualization (using OpenCV only) of the image given by the function 'getStructuringElement()' (as you can see, a binary image)
The image 'img_qt.png' is what I get when I convert the image cv::Mat to QImage and then put on a QLabel (as seen, not like the first picture and it is not a binary image).
For this reason is that I understand that this is a problem with Qt, either to convert cv::Mat to QImage or place it on the QLabel.
Well, I hope I have shed some light on the subject (my apologies if I knew not adequately explain in the first post which was my problem).
Again, thanks in advance for any help or suggestions.
I tried your suggestion and indeed when it isn't rescaled QLabel content, the image looks as it should look.
However, it is a very small image (in some cases 3x3 pixels) and obviously you can hardly appreciate and most of the space inside the QLabel is empty. I need the image to fit the size of QLabel.
So, the question now would be:
Is it possible to scale the contents of the QLabel ('setScaledContents (true)') without the occurrence of this unwanted effect (The interpolation between black and white that you mention)?, How I can do?
Considering that the QPixmap you set is a paletted image; I think it's reasonable that Qt tries to create a good quality image by interpolating shades; especially when they exist in the palette.
One solution could be to make your palette all 0 except for index 255; hopefully Qt will only scale using colours in the palette.
Another solution is to use
QPixmap QPixmap::scaled(const QSize & size, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio, Qt::TransformationMode transformMode = Qt::FastTransformation) const
with Qt::FastTransformation, which hopefully would use nearest neighbour interpolation. You would scale your image up to the size you need and setScaledContents(false);
The third option is for you to draw your image at the size you need using a QPainter or bitmap editor so again, no scaling is needed.
I use QPixmap::sclaed(), but does not work... the image isn't scaled to the desired size ((It looks like it will stay the same size and the QLabel most, if not all, is empty).
Not sure if I'm using the function incorrectly:
I pass Qt::IgnoreAspectRatio, Qt::FastTransformation, and I pass the size of QLabel (the size at which I want the QPixmap be scaled).
Is it wrong?
I think you may have not realised that QPixmap::scaled() is const. You need something like
QPixmap resized = QPixmap::fromImage( vista ).scaled(ui->labelVistaEe->size(), Qt::IgnoreAspectRatio,Qt::FastTransformation);
ui->labelVistaEe->setPixmap( resized );
Excuse my previous post.
It was a mental lapse. Even before using the function Pixmap::scaled () I check the documentation of Qt and check how it works, but when the encoding using the function incorrectly.
I was doing something like the following:
QPixmap p = QPixmap::fromImage( vista );
p.scaled( / * parameters * / );
ui->labelVistaEe->setPixmap( p );
However, thanks for the clarification.