How to Use Sci-kit Learn reconstruct_from_patches_2d - python

I'm working on an imaging project that needs to read images, split them into overlapping patches, run some operation on the patches, and then recombine them into a single image. For this task, I decided to the sci-kit learn methods extract_patches_2d, and reconstruct_from_patches_2d.
https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.image.extract_patches_2d.html
https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.image.reconstruct_from_patches_2d.html
import numpy as np
import cv2
from sklearn.feature_extraction import image as extraction
img = cv2.imread("cat_small.jpg", cv2.IMREAD_COLOR)
grid_size = 500
images = extraction.extract_patches_2d(img, (grid_size, grid_size), max_patches=100)
image = extraction.reconstruct_from_patches_2d(images, img.shape)
cv2.imwrite("stack_overflow_test.jpg", image)
I can tell the extraction works correctly, since each of the patches can be saved as an individual image. The reconstruction does not work.
The image:
becomes:
Which looks entirely black when viewed on a white background, but does have some white pixels toward the top left (can be seen when opened in a separate tab). This same problem happens in grayscale.
I have tried adding astype(np.uint8) as explained in
How to convert array to image colour channel in python?
to no avail. How is this method used properly?

Related

What image formats are accepted by TensorFlow? I have a plt.image.AxesImage, which I want to convert to an image without saving, for a training set

I have a matplotlib.image.AxesImage plot like this:
matplotlib.image.AxesImage
I'm working on a machine learning project for image processing so will need to process thousands of plots like this, retain their information without saving the image file, and then pass it through the training algorithm. I am using TensorFlow. TensorFlow accepts PIL images so I'm trying to find a way to convert this sample matplotlib.image.AxesImage object into a PIL image but all the other guides I found on stackexchange don't quite work. I have inserted some useful code from my project below:
image = cv2.imread('test.jpg',0)
mask = np.zeros(image.shape[:2], dtype="uint8")
circle = cv2.circle(mask, (320,240), 20, 1, 200)
unmasked = np.ma.masked_where(circle == 0, image)
fig_unmasked = plt.imshow(unmasked)
plt.rcParams["figure.figsize"] = (600,300) #change the size of the matplotlib plot
plt.colorbar()
plt.close()
My goal is to convert fig_unmasked into a PIL image/or any compatible image object that TensorFlow will accept. I would appreciate any guidance/tips, thank you!

How to save grayscale image in Python?

I am trying to save a grayscale image using matplotlib savefig(). I find that the png file which is saved after the use of matplotlib savefig() is a bit different from the output image which is showed when the code runs. The output image which is generated when the code is running contains more details than the saved figure.
How can I save the output plot in such a manner that all details are stored in the output image?
My my code is given below:
import cv2
import matplotlib.pyplot as plt
plt.figure(1)
img_DR = cv2.imread(‘image.tif',0)
edges_DR = cv2.Canny(img_DR,20,40)
plt.imshow(edges_DR,cmap = 'gray')
plt.savefig('DR.png')
plt.show()
The input file (‘image.tif’) can be found from here.
Following is the output image which is generated when the code is running:
Below is the saved image:
Although the two aforementioned images denote the same picture, one can notice that they are slightly different. A keen look at the circular periphery of the two images shows that they are different.
Save the actual image to file, not the figure. The DPI between the figure and the actual created image from your processing will be different. Since you're using OpenCV, use cv2.imwrite. In your case:
cv2.imwrite('DR.png', edges_DR)
Use the PNG format as JPEG is lossy and would thus give you a reduction in quality to promote small file sizes. If accuracy is the key here, use a lossless compression standard and PNG is one example.
If you are somehow opposed to using OpenCV, Matplotlib has an equivalent image writing method called imsave which has the same syntax as cv2.imwrite:
plt.imsave('DR.png', edges_DR, cmap='gray')
Note that I am enforcing the colour map to be grayscale for imsave as it is not automatically inferred like how OpenCV writes images to file.
Since you are using cv2 to load the image, why not using it also to save it.
I think the command you are looking for is :
cv2.imwrite('gray.jpg', gray_image)
Using a DPI that matches the image size seems to make a difference.
The image is of size width=2240 and height=1488 (img_DR.shape). Using fig.get_size_inches() I see that the image size in inches is array([7.24, 5.34]). So an appropriate dpi is about 310 since 2240/7.24=309.4 and 1488/5.34=278.65.
Now I do plt.savefig('DR.png', dpi=310) and get
One experiment to do would be to choose a high enough DPI, calculate height and width of figure in inches, for example width_inch = width_pixel/DPI and set figure size using plt.figure(figsize=(width_inch, height_inch)), and see if the displayed image itself would increase/decrease in quality.
Hope this helps.

overlay an image and show lighter pixel at each pixel location

I have two black and white images that I would like to merge with the final image showing the lighter/ white pixel at each pixel location in both images. I tried the following code but it did not work.
background=Image.open('ABC.jpg').convert("RGBA")
overlay=Image.open('DEF.jpg').convert("RGBA")
background_width=1936
background_height=1863
background_width,background_height = background.size
overlay_resize= overlay.resize((background_width,background_height),Image.ANTIALIAS)
background.paste(overlay_resize, None, overlay_resize)
overlay=background.save("overlay.jpg")
fn=np.maximum(background,overlay)
fn1=PIL.Image.fromarray(fn)
plt.imshow(fnl)
plt.show()
The error message I get is cannot handle this data type. Any help or advice anyone could give would be great.
I think you are over-complicating things. You just need to read in both images and make them greyscale numpy arrays, then choose the lighter of the two pixels at each location.
So starting with these two images:
#!/usr/local/bin/python3
import numpy as np
from PIL import Image
# Open two input images and convert to greyscale numpy arrays
bg=np.array(Image.open('a.png').convert('L'))
fg=np.array(Image.open('b.png').convert('L'))
# Choose lighter pixel at each location
result=np.maximum(bg,fg)
# Save
Image.fromarray(result).save('result.png')
You will get this:
Keywords: numpy, Python, image, image processing, compose, blend, blend mode, lighten, lighter, Photoshop, equivalent, darken, overlay.

How to change intensity threshold in an image using python

I want to remove the background noise from microscopy images. I have tried different methods (hist equalization and morphological transformation methods) but I got the conclusion the best method is to remove low intensity pixels.
I can do this using photoshop:
As you can see, figure A is the original one. I have included the histogram, shown in the bottom insert. Applying the transformation in B, I get the desired final image, where background is removed. See the transformation I have applied in the bottom insert from B.
I start working on the python code:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('lamelipodia/Lam1.jpg', 1)
#get green channel to gray
img_g = img[:,:,1]
#get histogram
plt.hist(img_g.flatten(), 100, [0,100], color = 'g')
cv2.imshow('b/w',img_g)
#cv2.imwrite('bw.jpg',img_g)
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()
I converted the figure to black and white
and got the histogram:
Which is similar to the one from photoshop.
I have been browsing google and SO but although I found similar questions, I could not find how to modify the histogram as I described.
How can I apply this kind of transformations using python (numpy or openCV)? Or if you think this has been responded before, please let me know. I apologize, but I have been really looking for this.
Following Piglet link:
docs.opencv.org/3.3.1/d7/d4d/tutorial_py_thresholding.html,the function is needed for the goal is:
ret,thresh5 = cv2.threshold(img_g,150,255,cv2.THRESH_TOZERO)
This is not easy to read.
We have to understand as:
if any pixel in the image_g is less than 150 then make it ZERO, keep the rest the same value as it was.
If we apply this to the image, we get:
The trick on how to read the function is by the added style. For example, cv2.THRESH_BINARY makes it read it as:
if any pixel in the image_g is less than 150 then make it ZERO (black), the rest make it 255 (white)

Viewing one layer of a pyramid image Python

I'm trying to view the second largest layer from a pyramid image that has already been created. I am finding lots of tutorials on how to create pyramid images, but not so much info on how to specifically view layers of a pre-made image. I was previously trying to use cv2 and matplotlib to view my image, however I was getting some distortion by one of the image edges. The distortion looks almost like white noise on a TV screen.
This is the code I was using to try and view the image:
import matplotlib.pyplot as plt
import cv2
img = cv2.imread('test.tif')
plt.imshow(img)
plt.show()
The largest image layer is 5367 (width) by 3339 (height) pixels. Any suggestions on how to go about viewing these images would be greatly appreciated!

Categories