Valid Coin Mask True Pixels Error Outside or Beyond the Actual Mask Error
Info
This question is locked. Reopen it to edit or answer.
Show older comments
imread("testCoinImage3.png");
[testcoinMask,MaskedtestCoin] = segmentCoinFace(testCoinImage);
se = strel("disk", 4, 0);
testcoinMask = imfill(testcoinMask, "holes");
testcoinMask = imerode(testcoinMask, se);
imgFilt = imgaussfilt(MaskedtestCoin, 1, 'Padding', 'circular', 'FilterDomain', 'frequency', 'FilterSize', 3);
faceEdgeMask = edge(imgFilt, "sobel", 0.09, "both");
faceEdgeMask(~testcoinMask) = false;
seFE = strel("disk",75,0);
fEdgeMask = imfill(faceEdgeMask, "holes");
BW2 = imdilate(fEdgeMask,seFE);
validCoinMask = BW2 & testcoinMask;
se2 = strel('disk',75,0);
validcoinMask = imdilate(validCoinMask, se2);
coinProps = regionprops("table", validCoinMask, 'Area', 'Perimeter');
areas = table2array(coinProps(:, 'Area'));
range = [min(areas ) max(areas)];
validCoinMask = bwareafilt(validCoinMask, range);
imshow(validCoinMask)
function [BW,maskedImage] = segmentCoinFace(X)
%segmentImage Segment image using auto-generated code from Image Segmenter app
% [BW,MASKEDIMAGE] = segmentImage(X) segments image X using auto-generated
% code from the Image Segmenter app. The final segmentation is returned in
% BW, and a masked image is returned in MASKEDIMAGE.
% Auto-generated by imageSegmenter app on 08-Jul-2023
%----------------------------------------------------
% Adjust data to span data range.
X = imadjust(X);
% Threshold image with global threshold
BW = imbinarize(im2gray(X));
% Open mask with default
radius = 2;
decomposition = 0;
se = strel('disk', radius, decomposition);
BW = imopen(BW, se);testCoinImage = imread("testCoinImage3.png");
[testcoinMask,MaskedtestCoin] = segmentCoin(testCoinImage);
% Shrink the coin mask.
se = strel('disk', 3, 0);
testcoinMask = imfill(testcoinMask, 'holes'); % Fill any holes in it.
testcoinMask = imerode(testcoinMask, se); % Shrink by 3 layers of pixels.
% Find edges using original poster's code.
imgFilt = imgaussfilt(MaskedtestCoin,0.7,...
Padding="circular",FilterDomain="frequency",FilterSize=3);
faceEdgeMask = edge(imgFilt,"sobel",0.1,"both");
% Erase outside the shrunken coin mask to get rid of outer boundary.
faceEdgeMask(~testcoinMask) = false;
imshow(faceEdgeMask);
function [BW,maskedImage] = segmentCoin(X)
%segmentImage Segment image using auto-generated code from Image Segmenter app
% [BW,MASKEDIMAGE] = segmentImage(X) segments image X using auto-generated
% code from the Image Segmenter app. The final segmentation is returned in
% BW, and a masked image is returned in MASKEDIMAGE.
% Auto-generated by imageSegmenter app on 08-Jul-2023
%----------------------------------------------------
% Adjust data to span data range.
X = imadjust(X);
% Threshold image with global threshold
BW = imbinarize(im2gray(X));
% Open mask with default
radius = 2;
decomposition = 0;
se = strel('disk', radius, decomposition);
BW = imopen(BW, se);
% Close mask with default
radius = 2;
decomposition = 0;
se = strel('disk', radius, decomposition);
BW = imclose(BW, se);
% Fill holes
BW = imfill(BW, 'holes');
% Invert mask
BW = imcomplement(BW);
% Invert mask
BW = imcomplement(BW);
% Create masked image.
maskedImage = X;
maskedImage(~BW) = 0;
end
% Close mask with default
radius = 2;
decomposition = 0;
se = strel('disk', radius, decomposition);
BW = imclose(BW, se);
% Fill holes
BW = imfill(BW, 'holes');
% Invert mask
BW = imcomplement(BW);
% Invert mask
BW = imcomplement(BW);
% Create masked image.
maskedImage = X;
maskedImage(~BW) = 0;
end
in the se variable for structuring element , when I change the value to 4 it shows "Your valid coin mask has one or more true pixels outside valid coins," and when I change the se value to another value later on, it would show that it isn't covering all true valid coins . Please if you can help, I've been stuck on this since the past 3 days and I'm getting quite frustrated grrr. Thanks :)
2 Comments
Ahsan
on 19 Jul 2023
Cris LaPierre
on 29 Jul 2023
There is a forum in the course, and I have it on good authority that the course authors are very responsive. Have you tried asking your question there?
Answers (4)
Image Analyst
on 20 Jul 2023
0 votes
I don't think most of that is needed. I would just threshold, call imfill, and then call bwareaopen. The double imcomplement and imopen stuff are most likely not needed, however I can't run your code until tonight because I'm traveling and on a computer without MATLAB.
13 Comments
Ahsan
on 20 Jul 2023
Edited: Image Analyst
on 21 Jul 2023
Image Analyst
on 21 Jul 2023
I just ran this code and it throws no such error. However the algorithm is still crazy and bizarre and not robust. Do you want me to fix it?
Ariba
on 28 Jul 2023
please fix it for me, i'm also stuck and have tried several times
Image Analyst
on 28 Jul 2023
It's a generic, general purpose demo of how to threshold an image to find blobs, and then measure things about the blobs, and extract certain blobs based on their areas or diameters.
Ariba
on 28 Jul 2023
nope this is an assignment in an image processing code of coursera
this is code i have written for it now after 70 tries:
testImageIdx = randi([1,3])
testCoinImage = imread("testCoinImage"+testImageIdx+".png");
imshow(testCoinImage);
[validCoinMask,maskedCoinImage] = segmentCoin(testCoinImage);
imshow(validCoinMask)
imshow(maskedCoinImage)
bw = maskedCoinImage > 100;
imshow(bw)
coinSizes = regionprops("table",bw,"Area","Perimeter");
nDimes = coinSizes.Area < 4100;
nDimes = sum(nDimes);
nNickels = (coinSizes.Area > 4100 & coinSizes.Area <6000);
nNickels = sum(nNickels);
nQuarters = (coinSizes.Area > 6000 & coinSizes.Area < 7800);
nQuarters = sum(nQuarters);
nFiftyCents = coinSizes.Area > 7800;
nFiftyCents = sum(nFiftyCents);
USD = (nDimes * 0.10) + (nNickels * 0.05) + ...
(nQuarters * 0.25) + (nFiftyCents * 0.50)
%%
function [validCoinMask,maskedCoinImage] = segmentCoin(X)
%segmentImage Segment image using auto-generated code from Image Segmenter app
% [BW,MASKEDIMAGE] = segmentImage(X) segments image X using auto-generated
% code from the Image Segmenter app. The final segmentation is returned in
% BW, and a masked image is returned in MASKEDIMAGE.
% Auto-generated by imageSegmenter app on 31-Dec-2022
%----------------------------------------------------
% Threshold image - manual threshold
validCoinMask = im2gray(X) > 188;
% Close mask with default
radius = 15;
decomposition = 0;
se = strel('disk', radius, decomposition);
validCoinMask = imclose(validCoinMask, se);
% Create masked image.
maskedCoinImage = X;
maskedCoinImage(~validCoinMask) = 0;
end
Ariba
on 28 Jul 2023
and have updated again:
function [validCoinMask, testCoinMask] = segmentCoinFace(testCoinImage)
% Convert the image to grayscale if it is not already
if size(testCoinImage, 3) > 1
testCoinImage = rgb2gray(testCoinImage);
end
% Manual threshold
threshold = 0.5; % You may need to adjust this value
% Apply threshold to create an initial mask
testCoinMask = testCoinImage > threshold;
% Apply morphological operations
se = strel("disk", 25);
testCoinMask = imfill(testCoinMask, "holes");
testCoinMask = imerode(testCoinMask, se);
% Create masked image and apply Gaussian filter
MaskedtestCoin = testCoinImage;
MaskedtestCoin(~testCoinMask) = 0;
imgFilt = imgaussfilt(MaskedtestCoin, 1, "Padding", "circular", "FilterDomain", "frequency", "FilterSize", 3);
% Detect edges
faceEdgeMask = edge(imgFilt, "sobel", 0.04, "both");
faceEdgeMask(~testCoinMask) = false;
% Apply morphological operations
seFE = strel("disk", 60);
fEdgeMask = imfill(faceEdgeMask, "holes");
BW2 = imdilate(fEdgeMask, seFE);
validCoinMask = BW2 & testCoinMask;
% Apply dilation
se2 = strel('disk', 65);
validCoinMask = imdilate(validCoinMask, se2);
% Filter by area to select the blobs in a certain size range.
minArea = 5; % Define the minimum area of the coins
maxArea = 5000; % Define the maximum area of the coins
validCoinMask = bwareafilt(validCoinMask, [minArea, maxArea]);
% Compute properties of valid coins
coinProps = regionprops("table", validCoinMask, "Area", "Perimeter", "Centroid");
disp(coinProps);%
% Create masked image.
maskedCoinImage = X;
maskedCoinImage(~validCoinMask) = 0;
end
Ahsan
on 28 Jul 2023
Ahsan
on 28 Jul 2023
Ahsan
on 28 Jul 2023
Ahsan
on 29 Jul 2023
Ariba
on 29 Jul 2023
same, I have to complete it before the deadline anyhow
Ariba
on 31 Jul 2023
yes have posted questions
Image Analyst
on 29 Jul 2023
@Ahsan I threw out most of the unnecessary code and simplified it greatly. Here is what I got:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 18;
testCoinImage = imread("testCoinImage3.png");
subplot(2, 2, 1);
imshow(testCoinImage)
title('Original Image', 'FontSize', fontSize)
% Segment the image.
[coinMask, MaskedtestCoin] = segmentCoinFace(testCoinImage);
subplot(2, 2, 2);
imshow(coinMask)
title('Mask', 'FontSize', fontSize)
subplot(2, 2, 3);
imshow(MaskedtestCoin)
title('Masked Image', 'FontSize', fontSize)
% Measure areas and perimeters.
coinProps = regionprops(coinMask, 'Area', 'Perimeter');
allAreas = [coinProps.Area]
allPerimeters = [coinProps.Perimeter]
range = [min(allAreas) max(allAreas)]
subplot(2, 2, 4);
bar(allAreas);
grid on;
title('Coin Areas', 'FontSize', fontSize)
%===========================================================================
function [BW, maskedImage] = segmentCoinFace(inputImage)
%segmentImage Segment image using auto-generated code from Image Segmenter app
% [BW, MASKEDIMAGE] = segmentImage(X) segments image X using auto-generated
% code from the Image Segmenter app. The final segmentation is returned in
% BW, and a masked image is returned in MASKEDIMAGE.
% Auto-generated by imageSegmenter app on 08-Jul-2023
%----------------------------------------------------
% Threshold image with global threshold
BW = imbinarize(im2gray(inputImage));
% Fill holes
BW = imfill(BW, 'holes');
% Find areas so we know what size blobs to exclude..
% props = regionprops(BW, 'Area');
% allAreas = sort([props.Area])
% Throw out blobs less than 2000 in area.
BW = bwareaopen(BW, 2000);
% Create masked image.
maskedImage = inputImage;
maskedImage(~BW) = 0;
end

5 Comments
Ariba
on 31 Jul 2023
it's still not helping
Ariba
on 31 Jul 2023
it is segmentatiin all the coin, we need to segment valid coins only
Image Analyst
on 31 Jul 2023
What exactly defines a "valid" coin? I thought they all were. Is it the ones that are fairly smooth looking? I thought those were just over exposed. Have you tried computing the standard deviation of the blobs PixelValues?
Image Analyst
on 1 Aug 2023
So I guess the answer is "No, I didn't try what you said" about standard deviations.
OK, so here is how you could do it:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 18;
testCoinImage = imread("testCoinImage3.png");
subplot(2, 2, 1);
imshow(testCoinImage)
title('Original Image', 'FontSize', fontSize)
[coinMask, MaskedtestCoin] = segmentCoinFace(testCoinImage);
subplot(2, 2, 2);
imshow(coinMask)
title('Mask', 'FontSize', fontSize)
subplot(2, 2, 3);
imshow(MaskedtestCoin)
title('Masked Image', 'FontSize', fontSize)
% Measure areas and perimeters.
coinProps = regionprops(coinMask, testCoinImage, 'Area', 'Perimeter');
allAreas = [coinProps.Area]
allPerimeters = [coinProps.Perimeter]
range = [min(allAreas) max(allAreas)]
subplot(2, 2, 4);
bar(allAreas);
grid on;
title('Coin Areas', 'FontSize', fontSize)
%===========================================================================
function [BW, maskedImage] = segmentCoinFace(inputImage)
%segmentImage Segment image using auto-generated code from Image Segmenter app
% [BW, MASKEDIMAGE] = segmentImage(X) segments image X using auto-generated
% code from the Image Segmenter app. The final segmentation is returned in
% BW, and a masked image is returned in MASKEDIMAGE.
% Auto-generated by imageSegmenter app on 08-Jul-2023
%----------------------------------------------------
% Threshold image with global threshold
BW = imbinarize(im2gray(inputImage));
% Fill holes
BW = imfill(BW, 'holes');
% Find areas so we know what size blobs to exclude..
% props = regionprops(BW, 'Area');
% allAreas = sort([props.Area])
% Throw out blobs less than 2000 in area.
BW = bwareaopen(BW, 2000);
% Measure areas and perimeters.
labeledImage = bwlabel(BW);
coinProps = regionprops(BW, inputImage, 'PixelValues');
% Get the standard deviation of each coin
for k = 1 : numel(coinProps)
allSDs(k) = std(double(coinProps(k).PixelValues));
end
allSDs
% Get a mask of only where the StdDev is more than 15.
BW = ismember(labeledImage, find(allSDs >= 15));
% Create masked image.
maskedImage = inputImage;
maskedImage(~BW) = 0;
end

Ashutosh
on 24 Dec 2023
Edited: Walter Roberson
on 25 Dec 2023
Valid Coin Segmentation
For this problem your code will need to create a mask which completely segments only the valid coins. Use the variable name validCoinMask.
The solutions to the previous assignments include a foreground mask with true pixel regions where any circular object is present (testCoinMask), and another coin face edge mask with true pixels only within the regions of valid coins (faceEdgeMask). Therefore, one approach to this task is to dilate the true pixel regions in faceEdgeMask to be greater than or equal to the size of the corresponding foreground regions in testCoinMask, and logically combine the result with testCoinMask to extract the valid coin regions. NOTE: Be careful not to dilate so far you overlap regions for blanks in the foreground mask. (See the project reading for more details.)
As before, you will be assessed using a randomly chosen selection from the three test images, so it is a good idea to test your algorithm on each of them in MATLAB.
% Read the test coin image.
testCoinImage = imread("testCoinImage3.png");
imshow(testCoinImage);
% Segment the coin image to get the testcoinMask and MaskedtestCoin.
[testcoinMask, MaskedtestCoin] = segmentCoin(testCoinImage);
% Shrink the coin mask to focus on the coin regions.
se = strel('disk', 20, 0);
testcoinMask = imfill(testcoinMask, 'holes');
testcoinMask = imerode(testcoinMask, se);
% Apply Gaussian filter to the masked coin image.
imgFilt = imgaussfilt(MaskedtestCoin, 0.5, 'Padding', 'circular', 'FilterDomain', 'frequency', 'FilterSize', 3);
% Detect edges using the Sobel operator.
faceEdgeMask = edge(imgFilt, 'sobel', 0.05, 'both');
% Eliminate edges outside the shrunken coin mask.
faceEdgeMask(~testcoinMask) = false;
% Dilate the faceEdgeMask to cover valid coin regions.
se_dilate = strel('disk', 20, 0);
dilated_faceEdgeMask = imdilate(faceEdgeMask, se_dilate);
% Combine the dilated faceEdgeMask with testcoinMask to get validCoinMask.
validCoinMask = testcoinMask & dilated_faceEdgeMask;
% Display the validCoinMask.
figure;
imshow(validCoinMask);
title('Valid Coin Mask');
% Segment Coin Function
function [testcoinMask, MaskedtestCoin] = segmentCoin(X)
X = im2gray(X);
testcoinMask = im2gray(X) > 200;
radius = 12;
decomposition = 4;
se = strel('disk', radius, decomposition);
testcoinMask = imclose(testcoinMask, se);
MaskedtestCoin = X;
MaskedtestCoin(~testcoinMask) = 0;
end
im ghetting the same error where im not able to mast all of the valid coins. please help me out here i have a deadline.
5 Comments
DGM
on 24 Dec 2023
I agree with @Image Analyst's recommendations above. It would be a lot simpler to just create a mask that finds all coins, then identify the blank ones based on the variation within each region.
Ashutosh
on 24 Dec 2023
can you help me with the code
Image Analyst
on 24 Dec 2023
Instead of posting your homework question as an Answer to @Ahsan, start a new thread, tag it as homework, and attach your image. We can't determine why you're not able to get a mask of all the coins unless we have your image.
Cris LaPierre
on 25 Dec 2023
I'd also suggest asking your question in the course forum. You'll find the instructors are quite responsive, and will be more familiat with the techniques you are expected to use at this point in the course.
NABIL
on 13 Sep 2024
0 votes

Can anyone help solve the ‘Valid Coin Segmentation’ problem for the MathWorks certification?
1 Comment
Cris LaPierre
on 13 Sep 2024
Please ask your questions in the course forum. It is activiely monitored by the course instructors.
This question is locked.
Categories
Find more on Classification Ensembles in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!