Attempting to convert an image to grayscale, or better, binary - python-3.x

My basic plan here is to create an image recognition software that tracks the size of different bubbles. I basically have a compilation of pictures that constitute a video. I have it working as of right now using PIMS to import the files I need and place them into an array (rawframes). I can print my picture.
import numpy as np
import pandas as pd
import pims
from pims import pipeline
import trackpy as tp
import os
import matplotlib as mpl
import matplotlib.pyplot as plt
#pipeline
def binary(frame):
return frame[:, :, 1]
id_example = 1
rawframes = pims.ImageSequence(os.path.join('BubbleSize/90FoamQuality/DryFoams', 'T20190411_002_ (*).jpg'), process_func=binary)
plt.imshow(rawframes[id_example])
What I am trying to do here is convert the images from regular into black and white. I have not used many of the things I imported yet I know, this is a very preliminary step.
However, below is a before and after image comparison. Can someone help me out or walk me through these steps here? I get lost when it comes to filtering the images through python.
edit --> when I change my pipeline function to the below, I get the same green image
edit2 --> printing frame.shape and frame.dtype in binary pipeline respectively

Related

Unable to joint two geopandas data framesm due to 'rtree' error

There are two shapefiles. And I have extracted those two data using geopandas file. and it was successful.
File 1 :
zipfile_mobile = "zip://File Saved Location/2020-01-01_performance_mobile_tiles.zip"
mobile_tiles = gp.read_file(zipfile_mobile)
File : 2
zipfile = "zip://File Saved Location/tl_2019_us_county.zip"
counties = gp.read_file(zipfile)
Now I want to look for the intersection of those data. while run the following command I'm getting the error message as below.
ky_counties = counties.loc[counties['STATEFP'] == '21'].to_crs(4326)
But when I do the following error has occurred.
Spatial indexes require either `rtree` or `pygeos`. See installation instructions at https://geopandas.org/install.html
But already rtree has been installed.
Python: 3.9.1
Also, note that the following libraries are already imported.
import geopandas as gp
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from shapely.geometry import Point
from adjustText import adjust_text
import rtree
After I remove ".to_crs(4326)" from the below code, then code execution succeeded.
ky_counties = counties.loc[counties['STATEFP'] == '21'].to_crs(4326)
The same CRS can often be referred to in many ways. For example, one of the most commonly used CRS is the WGS84 latitude-longitude projection. This can be referred to using the authority code "EPSG:4326".
It means no need for this conversion in this case.

How to save images using matplotlib without displaying them?

I have multiple(in millions) numpy 2-D arrays which need to be saved. One can save an individual image like this:
import numpy as np
import matplotlib.pyplot as plt
surface_profile = np.empty((50,50)) #numpy array to be saved
plt.figure()
plt.imshow(surface_profile)
save_filename='filename.png'
plt.savefig(save_filename)
However this process also displays the image which I don't require. If I keep saving million images like this, I should somehow avoid imshow() function of matplotlib.
Any help???
PS: I forgot to mention that I am using Spyder.
Your problem is using plt.imshow(surface_profile) to create the image as this will always display the image as well.
This can be done using PIL, try the following,
from PIL import Image
import numpy as np
surface_profile = np.empty((50,50)) #numpy array to be saved
im = Image.fromarray(surface_profile)
im = im.convert('RGB')
save_filename="filename.png"
im.save(save_filename, "PNG")

Displaying both plt.show() images as Figure 1, Figure 2 at the same time

Running the following code, I am unable to display both images at the same time in separate windows, or go from figure1 to figure2 with the arrow button.
Currently I am able to get figure2, only when I close figure1.
I have tried the following code to generate separate "figure" labels.
from skimage import data, color, io
from matplotlib import pyplot as plt
rocket = data.rocket()
gray_scale_rocket = color.rgb2gray(rocket)
f1=plt.figure(1)
io.imshow(rocket)
plt.show()
f2=plt.figure(2)
io.imshow(gray_scale_rocket)
plt.show()
I expect to see two windows figure1 and figure2 to be viewable at the same time (without needing to close figure1 window first), displaying the rocket image in color and in grayscale.
You should remove the first call to plt.show(), which is blocking (meaning it stops execution until you are done with the window). When you leave only the second one, it will show both figures simultaneously.
The resulting code:
from skimage import data, color, io
from matplotlib import pyplot as plt
rocket = data.rocket()
gray_scale_rocket = color.rgb2gray(rocket)
f1=plt.figure(1)
io.imshow(rocket)
f2=plt.figure(2)
io.imshow(gray_scale_rocket)
plt.show()
behaves as you expect.

How to fix 'Cannot handle this data type' while trying to convert a numpy array into an image using PIL

I am trying to visualize music into an image by using sounddevice to input the sound and then converting it to a numpy array.
The array is 2D and so I convert it to 3D (otherwise I only get a single thin vertical line in the image).
However when I use PIL to show the image it says 'Cannot handle this datatype'
The code is mentioned below:
import sounddevice as sd
from scipy.io.wavfile import write
import soundfile as sf
import numpy
from numpy import zeros, newaxis
from PIL import Image
fs = 44100 # Sample rate
seconds = 3 # Duration of recording
myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=2)
sd.wait() # Wait until recording is finished
print(myrecording)
print(numpy.shape(myrecording))
write('output.wav', fs, myrecording) # Save as WAV file
filename = 'output.wav'
A=myrecording[:,:,newaxis]
print(A)
im = Image.fromarray((A * 255).astype(numpy.uint8))
im.show()
I expect to get an image which shows colours corresponding to the sound being inputted in
This depends a little bit on what you want to do.
You have two channels with n-samples ((nsamples, 2) ndarray); do you want each channel to be a column of the image where the color varies depending on what the value is? That is why you were getting a very narrow image when you just plot myrecording.
You do not really have the data to create a full 2D image, unless you reshape the time series data to be something more like a square (so it actually looks like an image), but then you sort of lose the time dependence nature that I think you are going for.

Grayscale .png to numpy array

Indeed, this question has been answered many times. However, as I am not allowed to add a comment to an answer due to "too low" reputation, I would like to discuss the solution presented in the most comprehensive answer.
Wouldn't the solution:
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt #Used in the comparison below
im = Image.open('file.png').convert('RGB') #Opens a picture in grayscale
pic = np.array(im)
im.close()
work properly? I am wondering whether unacceptable changes in the quality occur. I have noticed some differences (i.e. black rows at the top in plt.imshow()) when I display the image:
im.show() #Before closing
plt.imshow(pic)
but I don't know whether they are only inevitable consequences of converting to np.array.
PS - If it is important, I would mention that I prepare the image for color quantization (KMeans) and Floyd dithering.
PPS - If you advised me how not to post duplicate question but discuss answers directly - it would be really appreciated.
Try it and see!
from PIL import Image
import numpy as np
# Other answer method
im1 = Image.open('gray.png').convert('L')
im1 = np.stack((im1,)*3, axis=-1)
# Your method
im2 = Image.open('gray.png').convert('RGB')
im2 = np.array(im2)
# Test if identical
print(np.array_equal(im1,im2))
Sample Output
True
I would say the one aspect that is different, is that the method in the other answer will work (insofar as it actually makes a greyscale image where R=G=B) even if the input image is colour, whereas your method will produce a colour image.
I was working on doing a similar thing, and I'm not sure why but I ran into a bunch of issues. In the end this worked for me pretty well without loss of any data.
from PIL import Image
import numpy as np
img=np.array(Image.open(filename).convert('L'))
and to convert back:
import imageio
array = array.astype(np.uint8)
imageio.imwrite(newfilename, array)
edit: this only works for black and white images. Color images need 3D arrays rather than 2D arrays

Resources