How to create a grey image in python? - python

I tried to create a grey 3x3 pixel image in python, however the result is always a black image with several coloured pixels.
What I tried:
import numpy as np
from PIL import Image
greyimg = np.array([[[128]*3]*3]*3)
print(greyimg)
Image.fromarray(greyimg, 'RGB').save("test_grey.png")
What I expected:
a grey 3x3 image
What I got:
a coloured image

import numpy as np
from PIL import Image
import cv2
greyimg = np.array([[[128]*3]*3]*3,dtype=np.uint8)
print(greyimg)
Image.fromarray(greyimg, 'RGB').save("test_grey.png")

Related

PIL won't load RGB Image

I am trying to load this image into python (I provided a link because its 75mb): https://drive.google.com/file/d/1usiKRN1JQaIxTTo_HTXPwUj8LeyR8CDc/view?usp=sharing
My current code is below, it loads the image and when you png.show() the image it displays it in RBG but when converted to a numpy array its shape is only (h, w) not (h, w, 3) for RGB.
Code:
import numpy as np
from PIL import Image
Image.MAX_IMAGE_PIXELS = 233280000
png = Image.open('world.png')
png.show()
png = np.array(png)
print(png.shape)
Try this instead:
import numpy as np
from PIL import Image
Image.MAX_IMAGE_PIXELS = 233280000
png = Image.open('world.png').convert('RGB')
png.show()
png = np.array(png)
print(png.shape)

Is there a Python algorithm to detect nucleii in GFP cells?

I have been trying to make an algorithm that can detect the nucleii in GFP cell scans like this one:
GFP Cell Scan
for months. I want it to be able to output:
desired_cell_tracking
Is there an existing library for doing this, or is there a way to train my own basic ML classifier for this?
(I attached starter code that detects just the cell masks (but not nucleii))
###############################
# This code uses cellpose library to create a mask for each cell in 2 png files of GFP-channel cell scans.
###############################
#~~~~~~~~~~~~~~~~~~~~~~~~~
# GFP cell detection original libraries
from skimage.io import imread
import numpy as np
import time, os, sys
import matplotlib.pyplot as plt
import matplotlib as mpl
import fnmatch
mpl.rcParams['figure.dpi'] = 300
from cellpose import utils, io
from skimage.measure import label, regionprops, regionprops_table
import pandas as pd
from PIL import Image, ImageChops
#~~~~~~~~~~~~~~~~~~~~~~~~~
# GFP cell nucleii detection libraries
from skimage import (filters, measure, morphology, segmentation)
from scipy import ndimage as ndi
from skimage import data, color
from skimage.transform import hough_circle, hough_circle_peaks
from skimage.feature import canny
from skimage.draw import circle_perimeter
from skimage.util import img_as_ubyte
import cv2
#~~~~~~~~~~~~~~~~~~~~~~~~~
# Load images
print("Libraries imported")
GFP_files = []
GFP_files.append('03152021_GFP_cells_1_lowesy_quality.tif')
GFP_files.append('03152021_GFP_cells_2_lowesy_quality.tif')
GFP_files= sorted(GFP_files) #sorting files
plt.figure(figsize=(2,2))
img = np.array(Image.open(GFP_files[0]))
img2 = img
wid = img.shape[0]
hei = img.shape[1]
#~~~~~~~~~~~~~~~~~~~~~~~~~
# Detect GFP cells
from cellpose import models, io
import random
model = models.Cellpose(gpu=True, model_type='cyto')
channels = [2,0]
#~~~~~~~~~~~~~~~~~~~~~~~~~
# LOOPING THROUGH FILES
#defining a null array for number of cells.
imgname=[0]*len(GFP_files)
n_cell= [[2, 0]]*len(GFP_files)
seg_masks=np.zeros((len(GFP_files), wid,hei)) #saving mask as 3d array for all images
i=-1 #for indexing
kernel = np.ones((5,5), np.uint8)
print('Running...')
# THE BIG LOOP
for filename in GFP_files:
i+=1
img = np.array(Image.open(filename))
masks, flows, styles, diams = model.eval(img, diameter=30, channels=channels)
n_cell[i]= [filename,np.max(masks)]
seg_masks[i,:,:]= masks
imgname[i]=[filename]
im = np.copy(img[:,:,0])
im[masks==0]=0 #set main background threshold on
# 'im' now is a single-color-channel image that only has one of the cells in it, everything else is background.

Colour intensity is changing when stacking numpy image arrays

I am loading an image from here, which is saved as .nii.gz. The image opens fine (with a dimension of (497x497)), and when displayed using matplotlib, it shows with correct intensities, as shown below:
When we are trying to make it a 3 channel image, by stacking the numpy array, and after plotting it, the intensity changes, as shown below:
Any idea how to resolve this? The minimal code to reproduce the problem in google colaboratory is present here:
import cv2
import glob
import numpy as np
import nibabel as nib
import skimage.io as io
from nibabel import nifti1
import matplotlib.pyplot as plt
! wget "https://github.com/Jimut123/simply_junk/blob/main/image.nii.gz?raw=true" -O image.nii.gz
image_file_name = "image.nii.gz"
print(image_file_name)
epi_img = nib.load(image_file_name)
epi_img_data = epi_img.get_fdata()
epi_img_data = epi_img_data/epi_img_data.max()
# epi_img_data = epi_img_data[..., np.newaxis]
plt.imshow(epi_img_data)
plt.show()
total_mask = np.stack((epi_img_data,)*3, axis=-1)
plt.imshow(total_mask,cmap='gray')
plt.show()
Like for example this is a 3-channel image (RGB):
But this looks exactly like it's grayscale version. For the above image, when stacking numpy arrays, I cannot make the image look similar to the grayscale one.
If you scale it as Cristolph and Johan described, the 3-channel plot becomes identical:
epi_img_data -= epi_img_data.min()
epi_img_data /= epi_img_data.max()
total_mask = np.stack((epi_img_data,)*3, axis=-1)
plt.imshow(total_mask)

Rotate an image without averaging pixel values

Is it possible to rotate an image and keep the true values? When I rotate a black and white image I get back grey values. Can I rotate without averaging the pixel values? I can almost do it manually by using np.where() but it gets difficult when there are more than 2 pixel values.
Code:
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
from scipy import ndimage
import cv2
filename = 'rot square.png'
img = cv2.imread('square test.png')
img_rot = ndimage.rotate(img, 10, reshape = False)
cv2.imwrite(filename, img_rot)
Original Image
Rotated Image
Averaged Values
True Values
Here:
from PIL import Image
img = Image.open('original.png')
rotated = img.rotate(45)
rotated.save('rotated.png')

How to compute colored pixel area on images using Python?

import numpy as np
from matplotlib import cm
from matplotlib import pyplot as plt
import Image
from scipy import ndimage
import Image, ImageDraw
import PIL
import cv
import cv2
from scipy.ndimage import measurements, morphology
from PIL import Image
from numpy import *
from scipy.ndimage import filters
import pylab
img = np.asarray(Image.open('test.tif').convert('L')) #read and convert image
img = 1 * (img < 127) # threshold
plt.imshow(img, cmap=cm.Greys_r) # show as black and white
plt.show()
Code above gives white pixels on black background, how to compute white region on image, then to split image into 100 rectangles and find rectangles with min, max and average numbers of pixels? thanks
Since your image is binary you can just sum the values to get a count of the white pixels.
from PIL import Image
import numpy as np
img = np.asarray(Image.open("foo.jpg").convert('L'))
img = 1 * (img < 127)
m,n = img.shape
# use np.sum to count white pixels
print("{} white pixels, out of {} pixels in total.".format(img.sum(), m*n))
# use slicing to count any sub part, for example from rows 300-320 and columns 400-440
print("{} white pixels in rectangle.".format(img[300:320,400:440].sum()))
Use slicing to pick out any rectangle and use sum() on that part.

Categories