Home > Blockchain >  OpenCV / Qt: how to convert gray scale image (OpenCV disparity) into a Qt QImage?
OpenCV / Qt: how to convert gray scale image (OpenCV disparity) into a Qt QImage?

Time:01-27

How to convert gray scale image (OpenCV disparity) into a Qt QImage?

Form the doc https://docs.opencv.org/4.x/dd/d53/tutorial_py_depthmap.html

>> wget https://raw.githubusercontent.com/canberkgurel/DisparityMapfromStereoPair/master/tsukuba_l.png
>> wget https://raw.githubusercontent.com/canberkgurel/DisparityMapfromStereoPair/master/tsukuba_r.png

>> python3
Python 3.9.8 (main, Nov  7 2021, 15:47:09) 
[GCC 11.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> import cv2 as cv
>>> from matplotlib import pyplot as plt
>>> imgL = cv.imread('tsukuba_l.png',0)
>>> imgR = cv.imread('tsukuba_r.png',0)
>>> stereo = cv.StereoBM_create(numDisparities=16, blockSize=15)
>>> disparity = stereo.compute(imgL,imgR)
>>> plt.imshow(disparity,'gray')
<matplotlib.image.AxesImage object at 0x7fe4f48bc640>
>>> plt.show()

OK, but now how to convert disparity to a Qt QImage? disparity looks like a gray image (2 dimensions, not 3)

>>> print(disparity.shape)
(288, 384)
>>> print(disparity)
[[-16 -16 -16 ... -16 -16 -16]
 [-16 -16 -16 ... -16 -16 -16]
 [-16 -16 -16 ... -16 -16 -16]
 ...
 [-16 -16 -16 ... -16 -16 -16]
 [-16 -16 -16 ... -16 -16 -16]
 [-16 -16 -16 ... -16 -16 -16]]
>>> print(np.mean(disparity))
85.20903862847223
>>> print(np.max(disparity))
240
>>> print(np.min(disparity))
-16

And conversion to RGB fails

>>> cv.cvtColor(disparity, cv.COLOR_GRAY2BGR)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
cv2.error: OpenCV(4.5.4) /tmp/pip-req-build-kv0l0wqx/opencv/modules/imgproc/src/color.simd_helpers.hpp:94: error: (-2:Unspecified error) in function 'cv::impl::{anonymous}::CvtHelper<VScn, VDcn, VDepth, sizePolicy>::CvtHelper(cv::InputArray, cv::OutputArray, int) [with VScn = cv::impl::{anonymous}::Set<1>; VDcn = cv::impl::{anonymous}::Set<3, 4>; VDepth = cv::impl::{anonymous}::Set<0, 2, 5>; cv::impl::{anonymous}::SizePolicy sizePolicy = cv::impl::<unnamed>::NONE; cv::InputArray = const cv::_InputArray&; cv::OutputArray = const cv::_OutputArray&]'
> Unsupported depth of input image:
>     'VDepth::contains(depth)'
> where
>     'depth' is 3 (CV_16S)

as RGB can be later transformed into QImage with

rgbImg = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
displayHeight, displayWidth, channel = rgbImg.shape
bytesPerLine = channel * displayWidth
qtImg = QImage(rgbImg.data, displayWidth, displayHeight, bytesPerLine, QImage.Format_RGB888)

CodePudding user response:

Finally found a direct way (without RGB conversion) to transform disparity into grey scaled QImage:

scaledDisparity = disparity - np.min(disparity)
if np.max(scaledDisparity) > 0:
    scaledDisparity = scaledDisparity * (255/np.max(scaledDisparity))
scaledDisparity = scaledDisparity.astype(np.uint8)
displayHeight, displayWidth = scaledDisparity.shape
channel = 1
bytesPerLine = channel * displayWidth
qtImg = QImage(scaledDisparity, displayWidth, displayHeight, bytesPerLine, QImage.Format_Indexed8)

CodePudding user response:

I was working in the past on something very similar. I created a whole proof of concept for blockmatching, stereocalibration and motion estimation using a QT UI in python.

Maybe you find it useful https://github.com/artofimagination/stereo-calibration-and-vSLAM

As for answering the actual question. Solved displaying the depth map like as follows.

grayLeft = cv2.cvtColor(frame.leftImage, cv2.COLOR_BGR2GRAY)
grayRight = cv2.cvtColor(frame.rightImage, cv2.COLOR_BGR2GRAY)

depth = stereoMatcher.compute(grayLeft, grayRight)
       
rgbDepth = cv2.cvtColor(
    depth.astype(np.uint8),
    cv2.COLOR_GRAY2RGB)

img = QImage(
    rgbDepth,
    rgbDepth.shape[1],
    rgbDepth.shape[0],
    QImage.Format_RGB888)
depthPix = QPixmap.fromImage(img)
  •  Tags:  
  • Related