Using Global Contrast Normalization - Python pylearn2 - python

Im attempting to input my image to this method, but when i try to draw the image, it comes totally black.
I tried inputing just one image and inputing the whole MNIST dataset.
Same result.
https://github.com/lisa-lab/pylearn2/blob/master/pylearn2/expr/preprocessing.py
if GCN is True:
trainingFolder = "../inputData/converted_training/GCN/"
testingFolder = "../inputData/converted_testing/GCN/"
img0 = (data[1,1:]).reshape((28,28)).astype('uint8')*255
im = Image.fromarray(img0)
im.show()
#GCN#
img_gcn = global_contrast_normalize(data)
img_gcn_1 = Image.fromarray(img_gcn[1,1:].reshape((28,28)).astype('uint8')*255)
img_gcn_1.show()
The second image, which is img_gcn_1 comes blacked.
What am i doing wrong?

Have you tried to visualize the image without multiplying by 255? i.e.,
import matplotlib.pyplot as plt
img = img_gcn[:, 0]
img = img.reshape(28, 28, order='F')
plt.imshow(img, cmap=plt.get_cmap('gray'))
I think that procedure should work.

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.

Understanding Handwritten digit by computer

i would like to ask you one question : wanted to implement a code which clarifies a picture done by hand ( by pen), let us consider such image
it is done by blue pen, which should be converted to the gray scale image using following code
from PIL import Image
user_test = filename
col = Image.open(user_test)
gray = col.convert('L')
bw = gray.point(lambda x: 0 if x<100 else 255, '1')
bw.save("bw_image.jpg")
bw
img_array = cv2.imread("bw_image.jpg", cv2.IMREAD_GRAYSCALE)
img_array = cv2.bitwise_not(img_array)
print(img_array.size)
plt.imshow(img_array, cmap = plt.cm.binary)
plt.show()
img_size = 28
new_array = cv2.resize(img_array, (img_size,img_size))
plt.imshow(new_array, cmap = plt.cm.binary)
plt.show()
idea is that i am taking image from camera directly, but it is losing structure of digit and comes only empty and black picture, like this
therefore computer can't understand which digit it is and neural networks fails to predict its label correctly, could you please tell me which transformation should i apply in order to detect this image much more precisely ?
edit :
i have apply following code
from PIL import Image
user_test = filename
col = Image.open(user_test)
gray = col.convert('L')
plt.hist(img_array)
plt.show()
and got
You have several issues here, and you can methodically address them.
First of all you're having an issue with thresholding properly.
As I suggested in earlier comments, you can easily see why your original thresholding was unsuccessful.
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
from matplotlib import cm
im = Image.open('whatever_path_you_choose.jpg').convert("L")
im = np.asarray(im)
plt.hist(im.flatten(), bins=np.arange(255));
Looking at the image you gave:
Clearly the threshold should be somewhere between 100-200, not as in your original code. Also note that this distribution isn't very bimodal - so I'm not sure otsu's method would work well here.
If we eyeball it (this can be tuned), we can see that thresholding at 145-ish gives decent results in terms of segmentation.
im_thresh = (im >= 145)
plt.imshow(im_thresh, cmap=cm.gray)
Now you might have an additional issue that you have horizontal lines, you can address this by writing on blank paper as suggested. This wasn't exactly your question but I will try to address it anyways (in a naive fashion). You can try a naive solution of using a sobel filter (think of it as the derivative of the image to get the lines), followed by a median filter to get the approximately most common pixel intensity - the size of the filter might have to vary for different digits though. This should clear up some of the lines. For a more rigorous approach try reading up on hough line transform for detecting horizontal lines and try to whiten them out.
This is my very naive approach:
from skimage.filters import sobel
from scipy.ndimage import median_filter
#Sobel filter reverses intensities so subtracting the result from 1.0 turns it back to the original
plt.imshow(1.0 - median_filter(sobel(im_thresh), [10, 3]), cmap=cm.gray)
You can try cropping automatically afterwards. Honestly I think most neural networks that could recognize MNIST-like digits could recognize the result I posted at the end as well.
Try using skimage package like this. This has inbuilt functions for image processing:
from skimage import io
from skimage.restoration import denoise_tv_chambolle
from skimage.filters import threshold_otsu
image = io.imread('path/to/your/image', as_gray=True)
# Denoising
denoised_image = denoise_tv_chambolle(image, weight=0.1, multichannel=True)
# Thresholding
threshold = threshold_otsu(denoised_image)
thresholded_image = denoised_image > threshold

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)
^^^^

Depth map shows everything grey! OpenCV- 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()

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