Depth map shows everything grey! OpenCV- Python - python

My code:
import cv2
import numpy as np
imgL = cv2.imread('Blender_Suzanne1.jpg')
img1 = cv2.cvtColor(imgL, cv2.COLOR_BGR2GRAY)
imgR = cv2.imread('Blender_Suzanne2.jpg')
img2 = cv2.cvtColor(imgR, cv2.COLOR_BGR2GRAY)
stereo = cv2.StereoBM_create(numDisparities = 16, blockSize = 17)
disparity = stereo.compute(img2, img1)
cv2.imshow('DepthMap', disparity)
cv2.waitKey()
cv2.destroyAllWindows()
When I run it, I see a window which is all grey? I think it is wrong.
I used this code from the OpenCV docs website.
Can anyone help?
PS: First I had some error which did not allow the output window to pop up. So, I added the two lines namely img1 and img 2 in my code.

You can display the result disparity using cv2.imshow() as well after you normalize it.
norm_image = cv2.normalize(disparity, None, alpha = 0, beta = 1, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_32F)
cv2.imshow('norm_image', norm_image)
Notice the change of data type after normalizing the image. Prior to normalization disparity was of type int16. After normalization it is float32 (mentioned within the function cv2.normalize())

Instead of using imshow use matplotlib to visualization as per the documentation. Also you can convert image into gray in the same line you read the image as follows.
import cv2
from matplotlib import pyplot as plt
imgL = cv2.imread('Blender_Suzanne1.jpg',0)
imgR = cv2.imread('Blender_Suzanne2.jpg',0)
stereo = cv2.StereoBM_create(numDisparities = 16, blockSize = 17)
disparity = stereo.compute(imgL, imgR)
plt.imshow(disparity,'gray')
plt.show()

Related

How to remove CT bed/shadows in a CT image with python?

I am working with 3D CT images and trying to remove the lines from the bed.
A slice from the original Image:
Following is my code to generate the mask:
segmentation = morphology.dilation(image_norm, np.ones((1, 1, 1)))
labels, label_nb = ndimage.label(segmentation)
label_count = np.bincount(labels.ravel().astype(int))
label_count[0] = 0
mask = labels == label_count.argmax()
mask = morphology.dilation(mask, np.ones((40, 40, 40)))
mask = ndimage.morphology.binary_fill_holes(mask)
mask = morphology.dilation(mask, np.ones((1, 1, 1)))
This results in the following image:
As you can see, in the above image the CT scan as distorted as well.
If I change: mask = morphology.dilation(mask, np.ones((40, 40, 40))) to mask = morphology.dilation(mask, np.ones((100, 100, 100))), the resulting image is as follows:
How can I remove only the two lines under the image without changing the image area? Any help is appreciated.
You've probably found another solution by now. Regardless, I've seen similar CT processing questions on SO, and figured it would be helpful to demonstrate a Scikit-Image solution. Here's the end result.
Here's the code to produce the above images.
from skimage import io, filters, color, morphology
import matplotlib.pyplot as plt
import numpy as np
image = color.rgba2rgb(
io.imread("ctimage.png")[9:-23,32:-9]
)
gray = color.rgb2gray(image)
tgray = gray > filters.threshold_otsu(gray)
keep_mask = morphology.remove_small_objects(tgray,min_size=463)
keep_mask = morphology.remove_small_holes(keep_mask)
maskedimg = np.einsum('ijk,ij->ijk',image,keep_mask)
fig,axes = plt.subplots(ncols=3)
image_list = [image,keep_mask,maskedimg]
title_list = ["Original","Mask","Imgage w/mask"]
for i,ax in enumerate(axes):
ax.imshow(image_list[i])
ax.set_title(title_list[i])
ax.axis("off")
fig.tight_layout()
Notes on code
image = color.rgba2rgb(
io.imread("ctimage.png")[9:-23,32:-9]
)
gray = color.rgb2gray(image)
The image saved as RGBA when I loaded it from SO. It needs to be in grayscale for use in the threshold function.
Your image might already by in grayscale.
Also, the downloaded image showed axis markings. That's why I've trimmed the image.
maskedimg = np.einsum('ijk,ij->ijk',image,keep_mask)
I wanted to apply keep_mask to every channel of the RGB image. The mask is a 2D array, and the image is a 3D array. I referenced this previous question in order to apply the mask to the image.

Image Reconstruction (Erosion and Dilation) both gives black image as output

I am trying to remove the black spots from a face of this image using the erosion methods.
I have implemented:
img = skimage.io.imread('blemish.jpeg')
img = skimage.color.rgb2gray(img)
img_inten = skimage.exposure.rescale_intensity(img,in_range=(50,100))
diliation_seed = img_inten.copy()
diliation_seed[1:-1,1:-1] = img_inten.min()
mask = img_inten
eroded_img = skimage.morphology.reconstruction(diliation_seed,mask,method='dilation')
matplotlib.pyplot.imshow(eroded_img,cmap='gray')
My output is always a black image in both the cases. What is going wrong here?
rgb2gray is outputting an image as a matrix of floats, with values in [0;1]
So the rescale_intensity is just outputting a matrix of 0, since you ask for values between 50 and 100 and there is none in the gray img.
you can fix it like this :
import skimage
from skimage import data, exposure, img_as_float
from skimage.morphology import reconstruction
import matplotlib.pyplot as plt
img = skimage.io.imread('blemish.jpeg')
gray_img = 255*skimage.color.rgb2gray(img) # multiply by 255 to get back in the [0;255] range
img_inten = exposure.rescale_intensity(gray_img,in_range=(50,100))
diliation_seed = img_inten.copy()
diliation_seed[1:-1,1:-1] = img_inten.min()
mask = img_inten
eroded_img = reconstruction(diliation_seed,mask,method='dilation')
plt.imshow(eroded_img,cmap='gray')
plt.show()

cv2 treshold does not work correctly on second image

I am new to python and I was playing around with background subtraction to visualize changes in pre and post change images.
I wrote a short and simple script using the cv2 library:
#!/usr/bin/env python
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
#GRAYSCALE ONLY FOR TESTING
#Test with person appearing in image
img1 = cv.imread("images/1.jpg", 0)
img2 = cv.imread("images/2.jpg", 0)
img3 = cv.subtract(img1, img2)
ret,thresh1 = cv.threshold(img3,90,255,cv.THRESH_BINARY)
#Test with satelite image of japan landslide changes after earthquake
jl_before = cv.imread("images/japan_earthquake_before.jpg",0)
jl_after = cv.imread("images/japan_earthquake_after.jpg",0)
jl_subtraction = cv.subtract(jl_before, jl_after)
ret,thresh2 = cv.threshold(img3,20,255,cv.THRESH_BINARY)
images = [img1, img2, thresh1, jl_before, jl_after, thresh2]
titles = ["Image1", "Image2", "Changes", "Japan_Before", "Japan_After", "Japan_Changes" ]
for i in range(6):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
The result looks like this:
Why is the mask with changes from the first set of images present in the mask of the second set of images?
I used different variables, thresh1 and thresh2.
Any help would be greatly appreciated as I can't seem to find the problem.
Because you missed a change when copy pasting:
ret,thresh2 = cv.threshold(img3,20,255,cv.THRESH_BINARY)
^^^^

How can I add two or more images using matplotlib?

I read the images using imread and then I would like to compute the average image. How can I add(and divide) using matplotlib?
I'm searching for something like imadd in matlab.
Code:
img1 = matplotlib.image.imread("path")
img2 = matplotlib.image.imread("path1")
img3 = matplotlib.image.imread("path2")
Thanks
You can use the normal sum operations:
img4 = img1 + img2 + img3
This, however, is not exactly the same as imadd from matlab. Matplotlib works with RGB values from 0 to 1. As so the sum in some pixels will provide values superior to 1 (which for the array type is valid; the same would not be true if the data type were uint8). As so perform the following operation to guarantee that your data comes out correct:
img1 = matplotlib.image.imread("path1")
img2 = matplotlib.image.imread("path2")
img3 = np.clip(img1 + img2, 0, 1)
Notice that all images must have the same size.
matplotlib.image is probably what you are looking for. You'll also need numpy if you want to manipulate the images otherwise, because they are basically just arrays in the size of the image (e.g. 1920 x 1080) with 3 or 4 dimensions (RGB or RGBA).
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
img1 = mpimg.imread("foo.png")
img2 = mpimg.imread("bar.png")
Now you are setup for image manipulation. In the case that your images are both in the same format and size (e.g. RGB. Check by using img1.shape and img2.shape) you can do:
img3 = plt.imshow((img1 + img2) / 2)

histogram equalization for colored image give error using python opencv

Error : Assertion failed (0 < cn && cn <= CV_CN_MAX) in merge
In the merge function
cv2.merge(channels,img2)
if the arguments are replaced as shown:
cv2.merge(img2,channels)
it will not give an error, but the histograms will be the same before and after equalization. What can I do in this piece of code.
Code:
import cv2,cv
import cv2.cv as cv
import numpy as np
from matplotlib import pyplot as plt
capture = cv.CaptureFromCAM(0)
img = cv.QueryFrame(capture)
img_size = cv.GetSize(img)
width,height = img_size
size = width,height,3
channels = np.zeros(size , np.uint8)
while (1):
img = cv.QueryFrame(capture)
img = np.asarray(img[:,:])
cv2.imshow("original",img)
hist = cv2.calcHist([img],[2],None,[256],[0,256])
#convert img to YCR_CB
img2 = cv2.cvtColor(img,cv2.COLOR_BGR2YCR_CB)
#split image to Y, CR, CB
cv2.split(img2,channels)
#histogram equalization to Y-MATRIX
cv2.equalizeHist(channels[0],channels[0])
#merge this matrix to reconstruct our colored image
cv2.merge(channels,img2)
#convert this output image to rgb
rgb = cv2.cvtColor(img2,cv2.COLOR_YCR_CB2BGR)
hist2 = cv2.calcHist([rgb],[2],None,[256],[0,256])
plt.plot(hist)
plt.plot(hist2)
plt.show()
Instead of using split and merge, take advantage of numpy slicing.
img2[:, :, 0] = cv2.equalizeHist(img2[:, :, 0])
# or run a small loop over each channel
you got the split() wrong here. it returns the channels.
since you don't catch the return values, your channels are not initialized
>>> import cv2
>>> help(cv2.split)
Help on built-in function split in module cv2:
split(...)
split(m[, mv]) -> mv
so it should look like:
channels = cv2.split(img2)
and please, avoid the old cv api, instead stick with cv2 consistently. (use cv2.VideoCapture, not cv.CaptureFromCAM)

Categories