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])