How to calculate the average grayscale profile of an image? - python

I would like to calculate the average grayscale profile of an image.
In my next code I have the evolution of the grayscale of all the pixels of the image, but how to make the average? To obtain a single curve, the average of all the others. Thank you
import imageio
import numpy as np
from matplotlib.pyplot import *
from matplotlib import pyplot as plt
img = imread("lion.jpg")
#
red = img[:,:,0]
green = img[:,:,1]
blue = img[:,:,2]
#print(np.mean(img)
line = red[:,:]
#here How to calculate the average grayscale profile?
figure(figsize=(8,4))
plot(line)
plt.show()

If I understand correctly, you want to have a profile of the greyscale image along both directions of the image.
import numpy as np
from matplotlib import pyplot as plt
img = plt.imread("https://i.stack.imgur.com/9qe6z.png")
# convert to grayscale
gray = img.mean(axis=2)
# or
#gray = np.dot(rgb[...,:3], [0.299, 0.587, 0.114])
# profile along x -> mean along y
prof_x = gray.mean(axis=0)
# profile along y -> mean along x
prof_y = gray.mean(axis=1)
fig, (ax, ay) = plt.subplots(nrows=2, sharex=True, sharey=True)
ax.plot(prof_x, label="x profile")
ay.plot(prof_y, color="C1", label="y profile")
fig.legend()
plt.show()

Related

Remove precipitates oriented in line shape in microscopic image

I have some microscopic images where there are precipitates in single states and in some we have in horizontal or vertical lines. Now how should I remove these lines?
import matplotlib.pyplot as plt
import numpy as np
from scipy import ndimage as ndi
import cv2
import math
from skimage import (
color, feature, filters, measure, morphology, segmentation, util
)
# Sample1 - T61
image = cv2.imread(r"C:\Users\Stelle1.tif",cv2.IMREAD_GRAYSCALE)
assert not isinstance(image,type(None)), 'image not found'
fig, ax = plt.subplots()
ax.imshow(image, cmap='gray')
ax.axis('off')
plt.imshow()
click to view the image
fig, ax = plt.subplots(figsize=(5, 5))
qcs = ax.contour(image, origin='image')
ax.axis('off')
plt.show()
thresholds = filters.threshold_multiotsu(image, classes=3)
regions = np.digitize(image, bins=thresholds)
fig, ax = plt.subplots(ncols=2, figsize=(10, 5))
ax[0].imshow(image)
ax[0].set_title('Original')
ax[0].axis('off')
ax[1].imshow(regions)
ax[1].set_title('Multi-Otsu thresholding')
ax[1].axis('off')
plt.show()
cells = image > thresholds[0]
dividing = image > thresholds[1]
labeled_cells = measure.label(cells)
labeled_dividing = measure.label(dividing)
naive_mi = labeled_dividing.max() / labeled_cells.max()
print(naive_mi)
higher_threshold = 100
dividing = image > higher_threshold
smoother_dividing = filters.rank.mean(util.img_as_ubyte(dividing),
morphology.disk(4))
binary_smoother_dividing = smoother_dividing > 20
fig, ax = plt.subplots(figsize=(5, 5))
ax.imshow(binary_smoother_dividing)
ax.set_title('Dividing precipitate')
ax.axis('off')
plt.show()
click to view the image
Here is what I got if I increase the higher_threshold = 100, I will lose the ellipse shape precipitate where I need to count the area and other properties. Can you suggest some solution that the algorithm should not detect the line shape precipitates?
Have you thought about using something like a hough transform to detect straight lines?:
https://scikit-image.org/docs/dev/auto_examples/edges/plot_line_hough_transform.html
I basically lifted this straight from the above tutorial and got some pretty decent out of the box results.
from skimage import io
from skimage.transform import probabilistic_hough_line
from skimage.feature import canny
img = io.imread('GsSj9.png', as_gray=True) # read in the image
edges = canny(img) # use canny filter to detect edges
lines = probabilistic_hough_line(edges, threshold=20, line_length=20, line_gap=3)
# make plot of image and probabilistic_hough_line
fig, axes = plt.subplots(1, 2, sharex=True, sharey=True)
ax = axes.ravel()
ax[0].imshow(img)
ax[0].set_title('image')
ax[1].imshow(img * 0)
for line in lines:
p0, p1 = line
ax[1].plot((p0[0], p1[0]), (p0[1], p1[1]))
ax[1].set_xlim((0, img.shape[1]))
ax[1].set_ylim((img.shape[0], 0))
ax[1].set_title('Probabilistic Hough')
You would still need to figure out a good way to make a binary image from the transform lines but it could be useful in your endeavor.

How to add gaussian noise to an image in the frequency domain using numpy?

I'm new to image processing and I'm wondering how to add a gaussian noise to grayscale image in the frequency domain. I know how to do this in the spatial domain.
import imageio
import numpy as np
import matplotlib.pyplot as plt
mean = 50
var = 50
sigma = var ** 0.5
image = imageio.imread('Pictures/Picture.jpg')
noisy_image = np.copy(image)
for i in range(image.shape[0]):
for j in range(image.shape[1]):
noisy_image[i][j] += np.random.normal(mean, sigma, (1,1))
figure, a = plt.subplots(1,2)
a[0].imshow(image, cmap='gray')
a[0].set_title('original image')
a[1].imshow(noisy_image, cmap='gray')
a[1].set_title('noisy image')
plt.show()
But when I try the same process in the frequency domain it won't work.
import imageio
import numpy as np
import matplotlib.pyplot as plt
mean = 50
var = 50
sigma = var ** 0.5
image = imageio.imread('Pictures/Picture.jpg')
noisy_image = np.copy(image)
# transformation to the frequency domain
noisy_image = np.fft.fft2(noisy_image)
for i in range(image.shape[0]):
for j in range(image.shape[1]):
noisy_image[i][j] += np.complex(np.random.normal(mean, sigma, (1,1)))
# transformation back to the spatial domain
image_noisy = np.real(np.fft.ifft2(image_noisy))
figure, a = plt.subplots(1,2)
a[0].imshow(image, cmap='gray')
a[0].set_title('original image')
a[1].imshow(noisy_image, cmap='gray')
a[1].set_title('noisy image')
plt.show()

Combine picture and plot with matplotlib with alpha channel

I have a .png image with alpha channel and a random pattern generated with numpy.
I want to supperpose both images using matplotlib. The bottom image must be the random pattern and over this, I want to see the second image (attached in the end of the post).
The code for both images is the following:
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
# Random image pattern
fig = plt.subplots(figsize = (20,4))
x = np.arange(0,2000,1)
y = np.arange(0,284,1)
X,Y = np.meshgrid(x,y)
Z = 0.6+0.1*np.random.rand(284,2000)
Z[0,0] = 0
Z[1,1] = 1
# Plot the density map using nearest-neighbor interpolation
plt.pcolormesh(X,Y,Z,cmap = cm.gray)
The result is the following image:
To import the image, I use the following code:
# Sample data
fig = plt.subplots(figsize = (20,4))
# Plot the density map using nearest-neighbor interpolation
plt.imread("good_image_2.png")
plt.imshow(img)
print(img.shape)
The image is the following:
Thus, the final result that I want is:
You can make an image-like array for Z and then just use imshow to display it before the image of the buttons, etc. Note that this only works because your png has an alpha channel.
Code:
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
# Plot the density map using nearest-neighbor interpolation
img = plt.imread("image.png")
(xSize, ySize, cSize) = img.shape
x = np.arange(0,xSize,1)
y = np.arange(0,ySize,1)
X,Y = np.meshgrid(x,y)
Z = 0.6+0.1*np.random.rand(xSize,ySize)
Z[0,0] = 0
Z[1,1] = 1
# We need Z to have red, blue and green channels
# For a greyscale image these are all the same
Z=np.repeat(Z,3).reshape(xSize,ySize,3)
fig = plt.figure(figsize=(20,8))
ax = fig.add_subplot(111)
ax.imshow(Z, interpolation=None)
ax.imshow(img, interpolation=None)
fig.savefig('output.png')
Output:
You can also turn off axes if you prefer.
ax.axis('off')

Obtain box2d from superpixels segments

I am trying to use SLIC to obtain superpixels and get semantic segmentation of an image.
img = cv2.imread(img_name)
segments = slic(image, n_segments = numSegments, sigma = 3,convert2lab=True,max_iter=25)
How do I get the box2d for each of the segments? and if there a hierarchical tree of the segments how do I fetch that?
I did not read the original paper, but according to documentation it does not return a hierarchy.
I assume that you mean bounding boxes, so used the skimage example of Regionprops to get bounding boxes for each superpixel returned by SLIC.
Result:
Code:
from skimage.segmentation import slic
from skimage.data import astronaut
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from skimage.measure import label
from skimage.measure import regionprops
from skimage.color import label2rgb
img = astronaut()
segments = slic(img, n_segments=50, compactness = 100)
image_label_overlay = label2rgb(segments, image=img)
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6))
ax.imshow(image_label_overlay)
for region in regionprops(segments):
minr, minc, maxr, maxc = region.bbox
rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr,
fill=False, edgecolor='red', linewidth=2)
ax.add_patch(rect)
plt.show()

Why performing an histogram equalization by scikit image to a binary image i got a black image after mahotas conversion?

I used histogram equalization and adaptation for erase illumination from the grayscale images, but after the histogram equalization (i used scikit image python library) was good, during image conversion in mahotas something goes wrong. I got a picture total black. How can i fix it?
Source image:
Histogram equalization and adaptation;
Result after mahotas conversion.
conversion code from scikit to mahotas:
binimg = np.array(img_adapteq, dtype=np.bool)
Source code:
import scipy
import numpy as np
import pymorph as pm
import mahotas as mh
from skimage import morphology
from skimage import io
from matplotlib import pyplot as plt
from skimage import data, img_as_float
from skimage import exposure
def plot_img_and_hist(img, axes, bins=256):
"""Plot an image along with its histogram and cumulative histogram.
"""
img = img_as_float(img)
ax_img, ax_hist = axes
ax_cdf = ax_hist.twinx()
# Display image
ax_img.imshow(img, cmap=plt.cm.gray)
ax_img.set_axis_off()
# Display histogram
ax_hist.hist(img.ravel(), bins=bins, histtype='step', color='black')
ax_hist.ticklabel_format(axis='y', style='scientific', scilimits=(0, 0))
ax_hist.set_xlabel('Pixel intensity')
ax_hist.set_xlim(0, 1)
ax_hist.set_yticks([])
# Display cumulative distribution
img_cdf, bins = exposure.cumulative_distribution(img, bins)
ax_cdf.plot(bins, img_cdf, 'r')
ax_cdf.set_yticks([])
return ax_img, ax_hist, ax_cdf
mhgray = mh.imread(path,0)
binimg = mhgray[:,:,0]
print(type(binimg[0][0]))
thresh = mh.otsu(binimg)
gray =( binimg< thresh)
shape = list(gray.shape)
w = 0
if (shape[0] > shape[1]):
shape = shape[0]
else:
shape = shape[1]
if (shape < 100):
w = int((shape/100 )*1.5)
elif(shape > 100 and shape <420):
w = int((shape/100 )*2.5)
else:
w = int((shape/100)*4)
disk7 = pm.sedisk(w)
img = binimg
# Contrast stretching
p2 = np.percentile(img, 2)
p98 = np.percentile(img, 98)
img_rescale = exposure.rescale_intensity(img, in_range=(p2, p98))
# Equalization
img_eq = exposure.equalize_hist(img)
# Adaptive Equalization
img_adapteq = exposure.equalize_adapthist(img, clip_limit=0.03)
# Display results
f, axes = plt.subplots(2, 4, figsize=(8, 4))
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img, axes[:, 0])
ax_img.set_title('Low contrast image')
y_min, y_max = ax_hist.get_ylim()
ax_hist.set_ylabel('Number of pixels')
ax_hist.set_yticks(np.linspace(0, y_max, 5))
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_rescale, axes[:, 1])
ax_img.set_title('Contrast stretching')
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_eq, axes[:, 2])
ax_img.set_title('Histogram equalization')
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_adapteq, axes[:, 3])
ax_img.set_title('Adaptive equalization')
ax_cdf.set_ylabel('Fraction of total intensity')
ax_cdf.set_yticks(np.linspace(0, 1, 5))
# prevent overlap of y-axis labels
plt.subplots_adjust(wspace=0.4)
plt.show()
plt.gray()
plt.subplot(121)
plt.title("after histo")
plt.imshow(img_adapteq)
plt.show()
binimg = np.array(img_adapteq, dtype=np.bool)#uint16
plt.gray()
plt.subplot(121)
plt.title("after otsu")
plt.imshow(binimg)
plt.show()
imgbnbin = mh.morph.dilate(binimg, disk7)
#2
plt.gray()
plt.subplot(121)
plt.title("after dilate before close")
plt.imshow(imgbnbin)
plt.show()
imgbnbin = mh.morph.close(imgbnbin, disk7)
#2
plt.gray()
plt.subplot(121)
plt.title("before skeletonize")
plt.imshow(imgbnbin)
plt.show()
imgbnbin = mh.morph.close(imgbnbin, disk7)
out = morphology.skeletonize(imgbnbin>0)
The scikit-image algorithm probably returns a floating point image with values between 0 and 1. If you cast that to bool, you'll get all ones. You probably want
binimg = img_adapteq > 0.5
In general, also take note of the rescale_intensity function, which will take an image with values between 0 and 1 and return an image with values between 0 and 255.
from skimage import exposure
image = rescale_intensity(image, out_range=(0, 255))

Categories

Resources