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()
Related
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.
I have a data with coordinates X,Y similar to a Vertical Sine function, I want to fill the area between left edge and the curve generated using variable color with colormap on matplot, changes in color whith X value as the image (From Blue to Red). I've tried and get this result where start point and final point are conected by a line. I need to fill the left area.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
from matplotlib.patches import PathPatch
#Data
y=np.arange(0,10,0.01)
x=np.sin(y)*y+2
#Set Array
xx=np.asarray(x)
yy=np.asarray(y)
path = Path(np.array([xx,yy]).transpose())
patch = PathPatch(path, facecolor='none')
plt.gca().add_patch(patch)
im = plt.imshow(xx.reshape(yy.size,1), cmap=plt.cm.coolwarm,interpolation="nearest",
origin='left',extent=[-5,10,0,10],aspect="auto", clip_path=patch, clip_on=True)
im.set_clip_path(patch)
You could add two additional points lying on the y-axis to create the desired shape:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
from matplotlib.patches import PathPatch
y = np.linspace(0, 10, 200)
x = np.sin(y) * y + 2
path = Path(np.array([np.append(x, [-5, -5]), np.append(y, [y[-1], y[0]])]).T)
patch = PathPatch(path, facecolor='none')
plt.gca().add_patch(patch)
im = plt.imshow(x.reshape(y.size, 1), cmap=plt.cm.coolwarm, interpolation="nearest",
origin='lower', extent=[-5, 10, 0, 10], aspect="auto", clip_path=patch, clip_on=True)
plt.show()
I want to detect all the curves in an image. I'm using python. I tried below code but it didn't detect all the curves in the image (red dotted circles). Can anybody please help to to know the problem?
import numpy as np
import matplotlib.pyplot as plt
import cv2
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
image = cv2.imread('s5.png',0)
edges = canny(image, sigma=6, low_threshold=35, high_threshold=50)
hough_radii = np.arange(20, 35, 2)
hough_res = hough_circle(edges, hough_radii)
accums, cx, cy, radii = hough_circle_peaks(hough_res, hough_radii,
total_num_peaks=3)
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(10, 4))
image = color.gray2rgb(image)
for center_y, center_x, radius in zip(cy, cx, radii):
circy, circx = circle_perimeter(center_y, center_x, radius)
image[circy, circx] = (220, 20, 20)
ax.imshow(image, cmap=plt.cm.gray)
plt.show()
This is the output:
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()
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')