I have a problem in using imsegkmeans in a for loop

2 次查看(过去 30 天)
I'm using several tools in MatLab to segmentate a video I took with a camera. Everything seems to work well, except for the fact that when I ask MatLab to show me the pictures with imsegkmeans they turn out all in different shades of blue and even the binarized image is all blue. However, apparently it's just a matter of visualization, since I'm using the binarized image to extract height and widht of the object in the video and it works.
Here there is my code:
clear all
close all
clc
% This script performs a DLT transformation of a video each
% 25 frames (each second), plots the mean RGB value of the flame, classifies
% the flame in different cluster and determinates the widht and the height of
% the flame recorded by the camera
v = VideoReader('MAH00030_Trim.mp4');
nFrames = v.NumFrames;
n = 1:25:nFrames;
num = length(n);
% Initialize the level of Red, Green and Blue
meanRedLevels = zeros(num, 1);
meanGreenLevels = zeros(num, 1);
meanBlueLevels = zeros(num, 1);
% Initialize the height and the widht
height = zeros(1,num);
widht = zeros(1,num);
for frame = 1 : 25 : nFrames
% Extract the frame from the movie structure.
thisFrame = read(v, frame);
figure(1)
% Perform the DLT transformation
% Points in the image (in pixels)
pa = [1373 1490]';
pb = [1359 1240]';
pc = [2420 1219]';
pd = [2423 1468]';
% Refence Points (in mm)
A = [0 200]';
B = [0 0]';
C = [840 0]';
D = [840 200]';
pin = [pa pb pc pd]; % 2xN matrix of inputs
pout = [A B C D]; % 2xN matrix of output
H = fitgeotrans(pin',pout', 'projective');
[Iwarp, ref] = imwarp(thisFrame,H);
% Crop the image in order to visualize only the interesting area
croppedImage = imcrop(Iwarp, [230 50 450 350]); %imcrop(Image, [xmin ymin width height])
subplot(2,2,1)
image(croppedImage)
title('Video after DLT transformation')
drawnow;
axis image
axis off
hold on
% Isolate the flame from the background
gImage = rgb2gray(croppedImage);
mask = gImage > 210; % Whatever value will allow to see only the flame
mask = bwareaopen(mask, 1000); % Get rid of any small specks that might be there.
maskedImage = gImage; % Initialize
maskedImage(~mask) = 0; % Zero outside the mask
% Mask the image using bsxfun() function
maskedRgbImage = bsxfun(@times, croppedImage, cast(mask, class(croppedImage)));
% Mean R, G and B level of the flame
meanRedLevels(frame) = mean(mean(maskedRgbImage(:, :, 1)));
meanGreenLevels(frame) = mean(mean(maskedRgbImage(:, :, 2)));
meanBlueLevels(frame) = mean(mean(maskedRgbImage(:, :, 3)));
subplot(2, 2, 2);
hold on;
plot(meanRedLevels, 'r-');
plot(meanGreenLevels, 'g-');
plot(meanBlueLevels, 'b-');
grid on;
title('Mean Red, Green and Blue level')
xlabel('Frame [n°]')
ylabel('R, G and B level [-]')
% Segmentation of the flame with K-means method
nColors = 7;
pixel_labels = imsegkmeans(maskedRgbImage,nColors,'NumAttempts',3);
subplot(2,2,3)
image(pixel_labels)
title('Video divided in 7 clusters')
axis image off
drawnow;
% Find the height and the widht of the flame
binaryImage = imbinarize(gImage,0.8); % Fit the value of 0.8 in order to visualize only the flame
% Make sure there is only one blob
binaryImage = bwareafilt(binaryImage, 1);
% Label the image
labeledImage = logical(binaryImage);
subplot(2,2,4)
image(binaryImage);
axis off;
axis image;
title('Binarized video')
% Make measurements of bounding box
props(frame) = regionprops(labeledImage, 'BoundingBox');
widht(frame) = props(frame).BoundingBox(3);
height(frame) = props(frame).BoundingBox(4);
end
widht = widht(1:25:length(widht))*3.3;
height = height(1:25:length(height))*3.3;
X = 1:length(widht);
Y = 1:length(height);
figure(2)
subplot(1,2,1)
plot(X,widht)
title('Widht vs Time')
xlabel('Time [s]')
ylabel('Widht [mm]')
subplot(1,2,2)
plot(Y,height)
title('Height vs Time')
xlabel('Time [s]')
ylabel('Height [mm]')
The figure that comes out is the following:
However, if I try to run the code with only the clustering it works correctly. Can someone help me?

回答(1 个)

Sai Pavan
Sai Pavan 2024-5-29
Hello,
I understand that you want to resolve the blue color appearing when visualizing your processed image.
The issue with the images appearing in different shades of blue is because MATLAB applies the current colormap to the image data, which by default is often set to "parula", resulting in the blueish appearance for varying intensities. For binary images, which consist only of 0s and 1s, using a colormap makes the image appear all blue or shades of blue. To display these images as black and white, we should explicitly set the colormap to "gray" after using "image" function.
Please refer to the below code snippet that illustrates the steps to resolve the issue:
image(binaryImage);
colormap gray
Additionally, when displaying the results from "imsegkmeans", MATLAB treats the label matrix "pixel_labels" as a single-channel image, where each pixel value represents a cluster index. To visualize this effectively as a color-coded segmentation map, we can use "label2rgb" function to convert the label matrix into an RGB image as showin the code snippet below:
RGB_label = label2rgb(pixel_labels);
imshow(RGB_label);
Please refer to the below documentation to learn more about:
Hope it helps!

类别

Help CenterFile Exchange 中查找有关 Modify Image Colors 的更多信息

产品


版本

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by