I wanted to unwrap an image like in this C++ tutorial (https://docs.opencv.org/4.5.0/d9/dfb/tutorial_unwrap.html) and wanted to use python for this.
It is not possible to use the histogram unwrapping algorithm of opencv in python. In Pycharm, I got the error: "Process finished with exit code -1073741819 (0xC0000005)" after executing the function cv2.phase_unwrapping_HistogramPhaseUnwrapping.unwrapPhaseMap.
I used pip install opencv-contrib-python to get opencv for python.
```.py
import numpy as np
import cv2
import sys
print('python ' + sys.version)
print('numpy version: ' + np.__version__)
print('cv2 version: ' + cv2.__version__)
add_shadow_mask = False
X, Y = np.meshgrid(np.linspace(-1, 1, 512) * 5, np.linspace(-1, 1, 512) * 5)
img = -(X * X + Y * Y)
print('Image size: %dx%d pixels', img.shape[0], img.shape[1])
img = img + np.random.rand(img.shape[0], img.shape[1]) * 0.5
if add_shadow_mask:
shadow_mask = np.zeros_like(img)
shadow_mask[int(shadow_mask.shape[0] / 4): 3 * int(shadow_mask.shape[0] / 4),
int(shadow_mask.shape[1] / 4): 3 * int(shadow_mask.shape[1] / 4)] = 1
img[np.where(shadow_mask)] = 0
img = np.mod(img, 2 * np.pi)
img[(img == 0) & (img > 0)] = 2 * np.pi
img = img.astype(np.float32)
cv2.imshow('wrapped image', ((img+np.pi)/(2np.pi)255).astype(np.uint8))
cv2.waitKey(1)
cv2_unwrap_img = np.copy(img)
params = cv2.phase_unwrapping_HistogramPhaseUnwrapping_Params()
params.height = img.shape[0]
params.width = img.shape[1]
print('params.height: %i' % params.height)
print('params.width: %i' % params.width)
print('params.histThresh: %f' % params.histThresh)
print('params.nbrOfLargeBins: %i' % params.nbrOfLargeBins)
print('params.nbrOfSmallBins: %i' % params.nbrOfSmallBins)
unwrapping_instance = cv2.phase_unwrapping_HistogramPhaseUnwrapping()
unwrapping_instance.create(params)
if not add_shadow_mask:
unwrapping_instance.unwrapPhaseMap(img, cv2_unwrap_img, shadowMask=None)
else:
unwrapping_instance.unwrapPhaseMap(img, cv2_unwrap_img, shadowMask=shadow_mask)
cv2.imshow('wrapped image', ((cv2_unwrap_img+np.pi)/(2np.pi)255).astype(np.uint8))
cv2.waitKey(1)
```
I also re-installed OpenCV 4.5.0 via anaconda and I can still see the same problem (crashing at function unwrapPhaseMap).
python 3.7.9 (default, Aug 31 2020, 17:10:11) [MSC v.1916 64 bit (AMD64)]
numpy version: 1.19.1
cv2 version: 4.5.0
Image size: %dx%d pixels 512 512
params.height: 512
params.width: 512
params.histThresh: 29.608812
params.nbrOfLargeBins: 5
params.nbrOfSmallBins: 10
this is another case, where you cannot use the (python generated) object constructor, but where you have to use a create() function to obtain a valid object.
# not a valid object !!
unwrapping_instance = cv2.phase_unwrapping_HistogramPhaseUnwrapping()
# you're throwing away the actual instance (it does not work "in-place") !!
unwrapping_instance.create(params)
again, it's the same known problem as
o = cv2.ORB() # will crash if you call any method on it
o = cv2.ORB_create() # ok
here's a working version:
>>> import cv2, numpy as np
>>> img=np.random.rand(512,512)
>>> img.dtype
dtype('float64')
>>> img = img.astype(np.float32) # important, see comment below !
>>> img.dtype
dtype('float32')
>>> params = cv2.phase_unwrapping_HistogramPhaseUnwrapping_Params()
>>> params.height = img.shape[0]
>>> params.width = img.shape[1]
>>> unwrapping_instance = cv2.phase_unwrapping.HistogramPhaseUnwrapping_create(params)
>>> unwrapping_instance.unwrapPhaseMap(img)
array([[0.46003717, 0.57322496, 0.29821473, ..., 0.3278197 , 0.90027434,
0.16586247],
[0.26952022, 0.81003857, 0.31112662, ..., 0.7896576 , 0.27345425,
0.59084547],
[0.6687096 , 0.4159716 , 0.69473535, ..., 0.23015377, 0.75404686,
0.29580984],
...,
[0.3466923 , 0.31816754, 0.67690355, ..., 0.2545285 , 0.72241044,
0.496577 ],
[0.41468897, 0.35860705, 0.34866506, ..., 0.3936315 , 0.5833978 ,
0.05523415],
[0.20499845, 0.64845246, 0.5746443 , ..., 0.43141046, 0.42942145,
0.47305965]], dtype=float32)
note, that unwrapPhaseMap() expects a float32 image as input, and will crash without error given any other format.
there should be asserts (in the c++ code), and it should be explicitly mentioned in the docs
Hi berak,
thank you for helping me out with the object instance.
I already faced the problem with float32 and I checked the type of the shadowMask again: It should be uint8 with 0s and 255s. This is also working now.
The following code is an example for using the histogram unwrapping algorithm from OpenCV in python - feel free to use and to share. It would be nice to see more python example code of the OpenCV lib (especially for this incredible fast algorithm!)!
```.py
import numpy as np
import cv2
import sys
def float_to_uint8(image):
# Note: This function does histogram equalization from any range to range [0 255]
return ((image - np.min(np.min(image))) / np.max(np.max(image)) * 255).astype(np.uint8)
print('python ' + sys.version)
print('numpy version: ' + np.__version__)
print('cv2 version: ' + cv2.__version__)
add_shadow_mask = False
X, Y = np.meshgrid(np.linspace(-1, 1, 512) * 5, np.linspace(-1, 1, 512) * 5)
d = np.sqrt(XX+YY)
sigma = 3.0
mu = 0.0
img = np.exp(-((d-mu)2 / (2.0 * sigma2))) * 4.5 * 2*np.pi
print('Image size: %i x %i pixels' % (img.shape[0], img.shape[1]))
img = img + np.random.rand(img.shape[0], img.shape[1]) * 0.5
img = img.astype(np.float32)
cv2.imshow('image', float_to_uint8(img))
cv2.waitKey(1)
wrapped_img = np.copy(img)
wrapped_img = np.mod(wrapped_img, 2 * np.pi)
wrapped_img[(wrapped_img == 0) & (wrapped_img > 0)] = 2 * np.pi
if add_shadow_mask:
shadow_mask = np.ones_like(wrapped_img) * 255
shadow_mask[int(shadow_mask.shape[0] / 4): 3 * int(shadow_mask.shape[0] / 4),
int(shadow_mask.shape[1] / 4): 3 * int(shadow_mask.shape[1] / 4)] = 0
# Shadow mask must be uint8
shadow_mask = shadow_mask.astype(np.uint8)
wrapped_img[np.where(shadow_mask == 0)] = 0
cv2.imshow('wrapped image', float_to_uint8(wrapped_img))
cv2.waitKey(1)
unwrap_img = np.zeros_like(wrapped_img)
params = cv2.phase_unwrapping_HistogramPhaseUnwrapping_Params()
params.height = img.shape[0]
params.width = img.shape[1]
print('params.height: %i' % params.height)
print('params.width: %i' % params.width)
print('params.histThresh: %f' % params.histThresh)
print('params.nbrOfLargeBins: %i' % params.nbrOfLargeBins)
print('params.nbrOfSmallBins: %i' % params.nbrOfSmallBins)
unwrapping_instance = cv2.phase_unwrapping.HistogramPhaseUnwrapping_create(params)
print("wrapped_img type: " + str(wrapped_img.dtype)) # should be np.float32
print("unwrap_img type: " + str(unwrap_img.dtype)) # should be np.float32
if not add_shadow_mask:
unwrap_img = unwrapping_instance.unwrapPhaseMap(wrapped_img)
else:
# Check the type
print("shadow_mask type: " + str(shadow_mask.dtype)) # should be np.uint8
unwrap_img = unwrapping_instance.unwrapPhaseMap(wrapped_img, shadowMask=shadow_mask)
cv2.imshow('unwrapped image', float_to_uint8(unwrap_img))
cv2.waitKey(0)
```
Not sure if this is the 'right' way to do it but I ended up completely uninstalling anaconda and rebuilding it. When I then made a new virtual environment the problem resolved. If others have the same issue this might work too.
Hi,
I also used OpenCV 4.2.X installed with Anaconda and the anaconda-forge channel and the opencv unwrap phase package did not work.
You only have to update the opencv to the latest version (currently 4.5.X) with the following command:
conda update opencv -c conda-forge
Note:
before this check if you installed the opencv library with conda-forge using command conda list! it is also possible to use the pip installation pip install opencv-contrib. The opencv-contrib pip package does also provide the unwrap algorithm of opencv.
Most helpful comment
this is another case, where you cannot use the (python generated) object constructor, but where you have to use a
create()function to obtain a valid object.again, it's the same known problem as
here's a working version:
note, that
unwrapPhaseMap()expects a float32 image as input, and will crash without error given any other format.there should be asserts (in the c++ code), and it should be explicitly mentioned in the docs