[Scientific Image Processing] Using matlab to replace image-j is a bit troublesome, but very flexible!

Students who work in materials and biology fields should be familiar with image-j. A few days ago, a senior asked me to use image-j to analyze some pictures. However, after using it, I found that I was confused about the results because I didn’t understand the workflow of image-j. I am not sure, and the function of image-j cannot be expanded, and the processing effect of some pictures is not good, so I thought of using matlab to implement similar functions. Although there is no friendly interactive interface, fortunately, everyone can use this as a basis. , design your own functions to better suit your own research direction.
Test file and source program download address, extraction code: tcxa
Video tutorial (Bilibili)

?: Functions currently supported by V1.0:
: The opening and closing operation of the image, respectively corresponding to separating small connections and filling small holes
: Binarization: supports single automatic threshold, single manual threshold, manual interval threshold
: Filter particles: Support filtering based on roundness and filtering based on area size
: Image statistics: supports the proportion of particles in the whole image, the real area of the image, the real area of particles, and particle number statistics

After downloading, set the working directory of matlab.

Open the main.m file and start using it. I put all the places that need to be modified at the front:

It is recommended that when you first use test images, you set these two items as follows:

auto_segmentation = true; % Whether to use automatic threshold segmentation
Interval_segmentation = false; % Whether to use interval threshold segmentation

Full code

clear
clc
close all;%Close the picture
%% needs to be modified here
image_dir = 'test.png'; %Read the file and change it to the name of your picture
fill_image = false; % Whether to fill the image, true will enable expansion and corrosion
separate_image = false; %Whether to separate the image, true will enable corrosion and expansion
SE1 = strel('square',8); %Get a square structural element with a side length of 13. The size of the corroded and expanded structural elements can be adjusted to see the effect. It needs to be adjusted when the points are dense. It is invalid when dense_image is false.
colors = [0,255,0]; % adjust color, default red

auto_segmentation = false; % Whether to use automatic threshold segmentation
level = 200; %binarization threshold, this value is invalid when auto_segmentation is true

Interval_segmentation = false; % Whether to use interval threshold segmentation
lowerThreshold = 25; %Interval threshold segmentation lower limit, this value is invalid when Interval_segmentation is false
upperThreshold = 61; %Interval threshold segmentation upper limit, this value is invalid when Interval_segmentation is false

desiredCircularity_bottom = 0.0; %Set the lower limit of the desired circularity threshold. The larger the value, the rounder it is. The range is 0-1.
modify_threshold_top = false; %Do you need to modify the upper limit of the roundness threshold?
desiredCircularity_top = 0.6; % upper limit of circularity threshold, this value is invalid when threshold_top_modify is false

ruler_val = 50; % scale scalar value
unit = 'um^2'; % scale unit
ruler_l = 557; %pixel position of the left end of the scale (x)
ruler_r = 744; %pixel position of the right end of the scale (x)

particle_area_thres = 0; % lower limit of particle size threshold, unit is unit
%% preprocessing
imagetest1 = imread(image_dir);
imagetest_copy = imagetest1;
mysize=size(imagetest1);

if numel(mysize) == 2
  imagetest1 = cat(3,imagetest1,imagetest1,imagetest1); %Convert grayscale image to color image
  imagetest_copy = cat(3,imagetest_copy,imagetest_copy,imagetest_copy);
end
imagetest1 = rgb2gray(imagetest1);
imagetest1_copy = imagetest1;

imshow(imagetest_copy)
impixelinfo% Check the scale coordinates through the prompt in the lower left corner

%Filter = fspecial('average',[3,3]);

% gausFilter1 = fspecial('gaussian',[7,7],0.6);
% imagetest1 = imfilter(imagetest1,gausFilter1);
% imagetest_copy_Gau = imagetest1;

%imagetest_copy = rgb2gray(imagetest_copy);
%I2 = im2bw(imagetest1, 0.25);

if auto_segmentation
    fprintf(2,'Note that you use automatic threshold\
');
    level = graythresh(imagetest1);
    imagetest1 = imbinarize(imagetest1, level);
elseif (~auto_segmentation & amp; & amp;~Interval_segmentation)
    fprintf(2,'Note that you used manual threshold\
');
    imagetest1 = imbinarize(imagetest1, level/255);
end

if Interval_segmentation
    fprintf(2,'Note that you used an interval threshold\
');
    imagetest1 = (imagetest1_copy >= lowerThreshold) & amp; (imagetest1_copy <= upperThreshold);% interval binarization
end
%% corrosion plus expansion
if fill_image
    fprintf(2,'Note that you have padding enabled\
')
    imagetest1 = imdilate(imagetest1,SE1);
    imagetest1 = imerode(imagetest1,SE1);
end
if separate_image
    fprintf(2,'Note that you enable separation\
')
    imagetest1 = imerode(imagetest1,SE1);
    imagetest1 = imdilate(imagetest1,SE1);
end
%% roundness filter closed area
labeledImage = bwlabel(imagetest1);%enclosed space label
props = regionprops(labeledImage, 'Area', 'Perimeter');%instantiation
circularity = (4 * pi * [props.Area]) ./ ([props.Perimeter].^2 + 0.0001);% Find circularity

if ~modify_threshold_top
    desiredCircularity_top = max(circularity);% Set the upper limit of the desired circularity threshold, generally do not need to be touched
end
selectedLabels = find((desiredCircularity_top > circularity) & amp; (circularity> desiredCircularity_bottom));
selectedImage = ismember(labeledImage, selectedLabels);% Filter based on roundness value
fprintf(2,['The circularity threshold is set to:',num2str(desiredCircularity_bottom),'-',num2str(desiredCircularity_top),'\
']);
fprintf(2,['The area threshold is set to:',num2str(particle_area_thres),unit,'\
'])
%% show results
figure
subplot(2,2,1);
%imshow(imagetest1);
imshow(imagetest_copy);%original image
subplot(2,2,2);
imhist(imagetest_copy)

subplot(2,2,3);
%imshow(imagetest_copy_Gau);
imshow(selectedImage);% displays the image after filtering roundness
%% Solving and beautifying image results
sum1 = sum(selectedImage(:));% find the total number of pixels
m = size(imagetest_copy,1);
n = size(imagetest_copy,2);
sum2 = m * n;% total number of pixels in the original image
Proportion = sum1/sum2;% Find the proportion
disp(['The proportion of the selected area in the whole image:',num2str(Proportion*100),'%'])
real_area = m * n * (ruler_val / (ruler_r - ruler_l))^2;
disp(['Real area of the whole picture:',num2str(real_area),unit])
disp(['Real area of the selection:',num2str(real_area*Proportion),unit])

R = imagetest_copy(:,:,1);
G = imagetest_copy(:,:,2);
B = imagetest_copy(:,:,3);

%default red
R(selectedImage)=colors(1);
G(selectedImage)=colors(2);
B(selectedImage)=colors(3);
image_output=cat(3,R,G,B);

% I = double(selectedImage).*double(I)
% image_output = imfuse(imagetest_copy,I)

subplot(2,2,4);
imshow(image_output)% superposition of original image and red mask

image_output = uint8(image_output);
imwrite(image_output,'result.png')%save

selectedImage_copy = selectedImage;%binarized image
particle_area = regionprops(selectedImage_copy, 'Area');%instantiation
disp(['Total number of particles (after filtering based on roundness):',num2str(size(particle_area,1)),'number'])
particle_area_val = [particle_area.Area]*(ruler_val / (ruler_r - ruler_l))^2;% real world area

vector_particle = [];
for i= 1:size(particle_area_val,2)
    if particle_area_val(i) > particle_area_thres
        vector_particle = [vector_particle, particle_area_val(i)];
    end
end
labeledImage_2 = bwlabel(selectedImage_copy);%enclosed space label
selectedLabels_2 = find(particle_area_val > particle_area_thres);
selectedImage_copy = ismember(labeledImage_2, selectedLabels_2);% Filter based on area

figure
imshow(selectedImage_copy)

mean_particle_real = mean(vector_particle);
disp(['Number of particles after filtering based on area:',num2str(size(selectedLabels_2,2))])
disp(['Average real particle area after filtering based on area:',num2str(mean_particle_real),unit])