Particle segmentation from background image - image

Here in this image, all the black strands and small black dots you can see are particles (foreground) and the white, yellowish, greenish, grayish, and small bluish areas are the backgrounds. I am looking for an algorithm to extract the foreground and replace the background with some known color say: white. Can you please suggest to me a better solution to achieve the target?
Thank you

Simple color thresholding should work here. The idea is to isolate black by using HSV color thresholding with a lower/upper threshold range to obtain a mask then cv2.bitwise_and to get the filtered result
You didn't specify a language so here's an implementation in Python
Code
import cv2
import numpy as np
image = cv2.imread('1.jpg')
# Set minimum and maximum HSV values to display
lower = np.array([0,0,0])
upper = np.array([179,255,52])
# Convert to HSV format and color threshold
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
result = cv2.bitwise_and(image, image, mask=mask)
result[mask==0] = (255,255,255)
# Display
cv2.imshow('image', image)
cv2.imshow('mask', mask)
cv2.imshow('result', result)
# cv2.imwrite('result.png', result)
cv2.waitKey()
HSV color thresholder script with sliders, remember to change the image file path. You can play with the sliders to refine your segmentation.
import cv2
import numpy as np
def nothing(x):
pass
# Load image
image = cv2.imread('1.jpg')
# Create a window
cv2.namedWindow('image')
# Create trackbars for color change
# Hue is from 0-179 for Opencv
cv2.createTrackbar('HMin', 'image', 0, 179, nothing)
cv2.createTrackbar('SMin', 'image', 0, 255, nothing)
cv2.createTrackbar('VMin', 'image', 0, 255, nothing)
cv2.createTrackbar('HMax', 'image', 0, 179, nothing)
cv2.createTrackbar('SMax', 'image', 0, 255, nothing)
cv2.createTrackbar('VMax', 'image', 0, 255, nothing)
# Set default value for Max HSV trackbars
cv2.setTrackbarPos('HMax', 'image', 179)
cv2.setTrackbarPos('SMax', 'image', 255)
cv2.setTrackbarPos('VMax', 'image', 255)
# Initialize HSV min/max values
hMin = sMin = vMin = hMax = sMax = vMax = 0
phMin = psMin = pvMin = phMax = psMax = pvMax = 0
while(1):
# Get current positions of all trackbars
hMin = cv2.getTrackbarPos('HMin', 'image')
sMin = cv2.getTrackbarPos('SMin', 'image')
vMin = cv2.getTrackbarPos('VMin', 'image')
hMax = cv2.getTrackbarPos('HMax', 'image')
sMax = cv2.getTrackbarPos('SMax', 'image')
vMax = cv2.getTrackbarPos('VMax', 'image')
# Set minimum and maximum HSV values to display
lower = np.array([hMin, sMin, vMin])
upper = np.array([hMax, sMax, vMax])
# Convert to HSV format and color threshold
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
result = cv2.bitwise_and(image, image, mask=mask)
result[mask==0] = (255,255,255)
# Print if there is a change in HSV value
if((phMin != hMin) | (psMin != sMin) | (pvMin != vMin) | (phMax != hMax) | (psMax != sMax) | (pvMax != vMax) ):
print("(hMin = %d , sMin = %d, vMin = %d), (hMax = %d , sMax = %d, vMax = %d)" % (hMin , sMin , vMin, hMax, sMax , vMax))
phMin = hMin
psMin = sMin
pvMin = vMin
phMax = hMax
psMax = sMax
pvMax = vMax
# Display result image
cv2.imshow('image', result)
if cv2.waitKey(10) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()

Related

Fix aspect ratio of a scatter plot with an image

I've to plot multiple scatter and table in a grid space and I'm having a couple of issues with the relative position but most important with defining and maintaining the aspect ratio of the scatter plot.
I've written a script with "fake" data on it to describe my problem and a minimum "not working" example below.
What I have is a dataframe with x, and y positions of objects, and what I want to do is to put the corresponding image below.
Since the image can have an arbitrary aspect ratio I need to read the aspect ratio and construct the scatter plot in that way but I'm unable to make it work.
Another problem is connected with the invert_xaxis and invert_yaxis that don't work (I need that command since the scatter data are inverted.
I've used the following commands, and as far as I've understood each of them should block the aspect ratio of the scatter plot to the same ratio of the figure but they do not work.
The aspect ratio becomes corrected only when the figure is plotted but that eliminates the effect of axis inversion.
I've had a similar problem with setting the aspect ratio of plots without the addition of a figure, sometimes it worked but not with tight_layout.
It is obvious that I'm missing something important....but I'm unable to figure it out.
This is the fake data code:
###############################################################################
# fake data
#general data aspect ratio
image_height= 5 #4270
image_width = 10 # 8192
pix2scale = 0.3125
data_AR = image_height / image_width
#random data generation
data_width = image_width* pix2scale
data_height = image_height * pix2scale
data1x = np.random.uniform(-data_width/2, data_width/2, size=(40))
data1y = np.random.uniform(-data_height/2, data_height/2, size=(40))
data2x = np.random.uniform(-data_width/2, data_width/2, size=(40))
data2y = np.random.uniform(-data_height/2,data_height/2, size=(40))
temp_df1 = pd.DataFrame([data1x,data1y,['random1']*40],index = ['x','y','label']).T
temp_df2 = pd.DataFrame([data2x,data2y,['random2']*40],index = ['x','y','label']).T
df = pd.concat([temp_df1,temp_df2],axis = 0, ignore_index = True)
del temp_df1, temp_df2
#sample image generation of variable aspect ratio
img_size = (image_height, image_width)
R_layer = np.ones(shape= img_size)*0.50
G_layer = np.ones(shape= img_size)*0.50
B_layer = np.ones(shape= img_size)*0.50
A_layer = np.ones(shape= img_size)
img = np.dstack([R_layer,G_layer,B_layer,A_layer])
#add a mark at the top left of the image
for k in range(0,3):
for i in range(0,int(image_width*0.2*data_AR)):
for j in range(0,int(image_width*0.2)):
img[i,j,k] = 0
#add a mark at the center of the image
# get center coordinates of the image
center = [[2, 4], [2, 5]]
for k in range(0,3):
for point in center:
if k == 0:
img[point[0],point[1],k] = 1
else:
img[point[0],point[1],k] = 0
#show image
fig, ax = plt.subplots()
ax.imshow(img)
###############################################################################
this is the code that generates the image:
#%%
# sample code
# at this point IƬve already loaded the image, the pix2scale value
# and the df containing data points
#read image aspect ratio
img_AR = img.shape[0]/img.shape[1]
pixel_width = img.shape[1]
pixel_height = img.shape[0]
# each pixel correspond to 0.3125 unit (mm)
pix2scale = 0.3125
#define image position
#the center of the image need to be placed at (0,0)
#bottom left corner
left = - (pixel_width * pix2scale)/2
bottom = - (pixel_height * pix2scale)/2
right = left + (pixel_width * pix2scale)
top = bottom + (pixel_height * pix2scale)
extent = [left,right,bottom,top]
#figure definition
figure_width = 15 #inch
figure_AR = 1
scatter_AR = img_AR
#initialize figure
fig_s= plt.figure(figsize = (figure_width,figure_width*figure_AR))
gs = plt.GridSpec (3,3)
#scatter plot in ax1
ax1 = fig_s.add_subplot(gs[:2,:2])
g = sns.scatterplot( data = df,
x = 'x',
y = 'y',
hue = 'label',
ax =ax1
)
ax1.invert_xaxis()
ax1.invert_yaxis()
#resize the figure box
box = ax1.get_position()
ax1.set_position([box.x0,box.y0,box.width*0.4,box.width*0.4*scatter_AR])
ax1.legend(loc = 'center left', bbox_to_anchor = (1,0.5))
ax1.set_title('Inclusions Scatter Plot')
ax1.set_aspect(scatter_AR)
#plt image
ax1.imshow(img,extent = extent)
#scatter plot
ax2 = fig_s.add_subplot(gs[2,:2])
g = sns.scatterplot( data = df,
x = 'x',
y = 'y',
hue = 'label',
ax =ax2
)
#resize the figure box
box = ax2.get_position()
ax2.set_position([box.x0,box.y0,box.width*0.4,box.width*0.4*scatter_AR])
ax2.legend(loc = 'center left', bbox_to_anchor = (1,0.5))
ax2.set_title('Inclusions Scatter Plot')
ax2.set_aspect(scatter_AR)
ax2.imshow(img,extent = extent)
#scatter plot
ax3 = fig_s.add_subplot(gs[1,2])
g = sns.scatterplot( data = df,
x = 'x',
y = 'y',
hue = 'label',
ax =ax3
)
#resize the figure box
box = ax3.get_position()
ax3.set_position([box.x0,box.y0,box.width*0.4,box.width*0.4*scatter_AR])
ax3.legend(loc = 'center left', bbox_to_anchor = (1,0.5))
ax3.set_title('Inclusions Scatter Plot')
ax3.set_aspect(scatter_AR)
ax3.imshow(img,extent = extent)
#add suptitle to figure
fig_s.suptitle('my title',fontsize= 22)
fig_s.subplots_adjust(top=0.85)
# #make it fancy
for i in range(3):
fig_s.tight_layout()
plt.pause(0.2)
I've plotted multiple grid because I wanted to test the tight_layout().
[enter image description here][2]

PIL.ImageDraw.ImageDraw.text features attribute in Pillow 7.0.0 dosen't seem to give any difference in results

This is the code
img = np.full(shape=(40, 225, 3), fill_value=211, dtype=np.uint8)
b,g,r,a = 0,0,0,0
fontpath = "arial.ttf"
font = ImageFont.truetype(fontpath, 14)
img_pil = Image.fromarray(img)
draw = ImageDraw.Draw(img_pil)
draw.text((25, 10), captcha, font=font, features=['cpsp', 'dist'], fill=(b, g, r, a))
# w=img_pil.rotate(17.5, expand=1)
# img_pil = Image.paste( ImageOps.colorize(w, (0,0,0), (255,255,84)), (242,60), w)
img = np.array(img_pil)
noise_factor = np.random.uniform(low=0.4, high=0.8, size=1)
gauss = np.random.normal(0, noise_factor, img.size)
gauss = gauss.reshape(img.shape[0],img.shape[1],img.shape[2]).astype('uint8')
noise = img + img * gauss
## Display
gray = cv2.cvtColor(noise, cv2.COLOR_BGR2GRAY)
cv2.imwrite(captcha+".png", gray)
The above code didn't alter the space between the characters, am I using it right?
Please include some examples in https://pillow.readthedocs.io/en/stable/reference/ImageDraw.html on how to use this.
Click Here to see the output for the above code

How can i find center coordinates of a group object opencv

I want to center x,y coordinates of all delight lokums in this picture;
marshmallows on a tray
i tried a lot of things but i cant complete rectangles.
i get this image
enter image description here
target my project
project target
import cv2
import numpy as np
img = cv2.imread ('yl4.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#morphology
kernel = np.ones((3,3),np.uint8)
erosion = cv2.erode(gray,kernel,iterations = 1)
kernel = np.ones((17,17),np.uint8)
opening = cv2.morphologyEx(gray , cv2.MORPH_OPEN, kernel)
#get binary
gray_blur = cv2.GaussianBlur(opening, (21,21), 0)
thresh = cv2.adaptiveThreshold(gray_blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV, 11, 1)
kernel = np.ones((3,3),np.uint8)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = np.ones((7,7),np.uint8)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
#filter small dotted regions
nlabels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh , None, None, None, 4, cv2.CV_32S)
sizes = stats[1:, -1] #get CC_STAT_AREA component
img2 = np.zeros((labels.shape), np.uint8)
for i in range(0, nlabels - 1):
if sizes[i] >= 275:
img2[labels == i + 1] = 255
cv2.imshow('frame',img2)
cv2.imshow('gray',gray)
cv2.imwrite("outyl3.jpg", img2)
cv2.waitKey(0)

MATLAB second axis for colorbar following a convention

i want to make a second axis for the same colorbar of an false color image. the second scale should follow this convention : [new values] = Log10([old values]/108000)/-0.4 . i have this code for the first axis:
C = 10
hFig = figure('Name','False Color Luminance Map', 'ToolBar','none','MenuBar','none');
% Create/initialize default colormap of jet.
cmap = parula(16); % or 256, 64, 32 or whatever.
% Now make lowest values show up as black.
cmap(1,:) = 0;
% Now make highest values show up as white.
cmap(end,:) = 1;
imshow(J,'Colormap',cmap) % show Image in false color
colorbar % add colorbar
h = colorbar; % define colorbar as variable
caxis auto
y_Scl = (1/C);
yticks = get(h,'YTick');
set(h,'YTickLabel',sprintfc('%g', [yticks.*y_Scl]))
in a previous post here i got this lines for an second axis:
BarPos = get(hBar1,'position');
ylabel(hBar1,'label','FontSize',12);
haxes = axes('position',BarPos,'color','none','ytick',0:5:15,'ylim',[0 15],'xtick',[]);
how can i make the second axis use the the yticks of the first axis as an input for the convention?
EDIT: here is what i came up with. the thing is the values are wrong :/
fname='IMG_0041'; % select target image
C = 1000; % Constant to adjust image
K = 480; % Cameraconstant
RGB = imread([fname, '.tif']);% Read Image as tif
info = imfinfo([fname,'.CR2']); % get Metadata from CR2
x = info.DigitalCamera; % get EXIF
t = getfield(x, 'ExposureTime');% save ExposureTime
f = getfield(x, 'FNumber'); % save FNumber
S = getfield(x, 'ISOSpeedRatings');% save ISOSpeedRatings
date = getfield(x,'DateTimeOriginal'); % save DateTimeOriginal
I = rgb2gray(RGB); % convert Image to greyscale
% N_s = K*(t*S)/power(f,2))*L
L = power(f,2)/(K*t*S)*C; % calculate L/N_s
J = immultiply(I,L);
hFig = figure('Name','False Color Luminance Map', 'ToolBar','none', 'MenuBar','none');
% Create/initialize default colormap of jet.
cmap = parula(16); % or 256, 64, 32 or whatever.
% Now make lowest values show up as black.
cmap(1,:) = 0;
% Now make highest values show up as white.
cmap(end,:) = 1;
imshow(J,'Colormap',cmap) % show Image in false color
colorbar % add colorbar
h = colorbar; % define colorbar as variable
caxis auto
y_Scl = (1/C);
yticks = get(h,'YTick');
set(h,'YTickLabel',sprintfc('%g', [yticks.*y_Scl]))
BarPos = get(h,'position');
haxes = axes('position',BarPos,'color','none','ylim',[0 150]);
set(haxes,'YTickLabel', sprintfc('%g', log10(yticks.*y_Scl/108000)/-0.4));
https://www.sendspace.com/file/39wwm9 -> files for testing the code

Detecting rectangle in image

I would like to ask if somebody could help me with rectangle detection in image.
I've tried contour detection, but results are not sufficient.
I'd be thankful for any ideas.
I have tried this:
EDIT 1
# loading image
im = cv2.imread('b.jpeg',cv2.IMREAD_GRAYSCALE)
# equalization
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
im = clahe.apply(im)
# bluring image
im = cv2.GaussianBlur(im,(5,5),0)
# edge detection
edges = cv2.Canny(im,100,200)
cv2.imshow('Canny',edges)
cv2.moveWindow('Canny',0,0)
cv2.waitKey(0)
cv2.destroyAllWindows()
# contour extraction
ret,thresh = cv2.threshold(edges,50,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(im, contours, -1, (0,255,0), 3)
cv2.imshow('Contour',im)
cv2.moveWindow('Contour',0,0)
cv2.waitKey(0)
cv2.destroyAllWindows()
cntrRect = []
for i in contours:
approx = cv2.approxPolyDP(i,0.1*cv2.arcLength(i,True),True)
x,y,w,h = cv2.boundingRect(approx)
cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2)
#peri = cv2.arcLength(i,True)
epsilon = 0.1*cv2.arcLength(i,True)
#0.02*peri
approx = cv2.approxPolyDP(i,epsilon,True)
if len(approx) == 4:
cntrRect.append(approx)
cv2.imshow('Contour2',im)
cv2.moveWindow('Contour2',0,0)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.drawContours(im, cntrRect, -1, (255,0,0), 3)
cv2.imshow('Contour3',im)
cv2.moveWindow('Contour3',0,0)
cv2.waitKey(0)
cv2.destroyAllWindows()

Resources