Info
This question is locked. Reopen it to edit or answer.
Showing the error "Variable nDimes has an incorrect value"
8 views (last 30 days)
Show older comments
For this problem your code will need to do the following:
- Accurately determine the number of each coin type present. Use variable names nDimes, nNickels, nQuarters, and nFiftyCents.
- Calculate the total $ value of coins present. Use variable name USD
The code:
testImageIdx = randi([1,3]);
testCoinImage = imread("testCoinImage" + testImageIdx + ".png");
imshow(testCoinImage);
title("Original Coin Image");
[testcoinMask, MaskedtestCoin] = segmentCoin(testCoinImage);
se = strel('disk', 20, 0);
testCoinMask = imfill(testcoinMask, 'holes');
testCoinMask = imerode(testcoinMask, se);
imgFilt = imgaussfilt(MaskedtestCoin, 0.5, 'Padding', "circular", 'FilterDomain', "frequency", 'FilterSize', 3);
faceEdgeMask = edge(imgFilt, "sobel", 0.05, "both");
faceEdgeMask(~testcoinMask) = false;
imshow(faceEdgeMask);
title("Edge Mask Detection for Valid Coins");
see = strel("disk", 25, 0);
fb = imfill(faceEdgeMask, "holes");
Bw2 = imdilate(fb, see);
validCoinMask = Bw2 & testcoinMask;
set = strel("disk", 2, 0);
validCoinMask = imdilate(validCoinMask, set);
montage({testcoinMask, validCoinMask});
title("testcoinMask vs ValidCoinMask");
coinSizes = regionprops("table", validCoinMask, "Area");
nDimes = coinSizes.Area < 1100;
nDimes = sum(nDimes);
nNickels = (coinSizes.Area > 1100 & coinSizes.Area < 2200);
nNickels = sum(nNickels);
nQuarters = (coinSizes.Area > 2200 & coinSizes.Area < 3200);
nQuarters = sum(nQuarters);
nFiftyCents = coinSizes.Area >= 3200;
nFiftyCents = sum(nFiftyCents);
USD = (nDimes * 0.10) + (nNickels * 0.05) + (nQuarters * 0.25) + (nFiftyCents * 0.50);
function [testcoinMask, MaskedtestCoin] = segmentCoin(X)
X = im2gray(X);
testcoinMask = im2gray(X) > 150;
radius = 12;
decomp = 4;
se = strel('disk', radius, decomp);
testcoinMask = imclose(testcoinMask, se);
MaskedtestCoin = X;
MaskedtestCoin(~testcoinMask) = 0;
end
3 Comments
Accepted Answer
Cris LaPierre
on 2 Aug 2024
Edited: Cris LaPierre
on 2 Aug 2024
Inspect the criteria you are using to determine nDimes. Your code finds 11 dimes in each image, which is incorrect.
2 Comments
Cris LaPierre
on 4 Aug 2024
Edited: Cris LaPierre
on 4 Aug 2024
I believe the issue you are having is that your mask is not the area of the coins. This makes it difficult when using area to distinguish between coin types. Here is the validCoinMask your code is creating:
I had to change the range of areas your code uses to identify the coins, and it still was getting some wrong because of this.
You want your mask to look like this (both are masks for test image 1).
More Answers (2)
martin
on 24 Aug 2024
Edited: Walter Roberson
on 31 Aug 2024
testImageIdx = randi([1,3])
testCoinImage = imread("testCoinImage"+testImageIdx+".png");
imshow(testCoinImage);
title("Original Coin Image");
[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);
faceEdgeMask = edge(imgFilt, 'sobel', 0.05, 'both');
% Eliminate edges outside the shrunken coin mask
faceEdgeMask(~testcoinMask) = false;
imshow(faceEdgeMask);
title("Edge Mask Detection for Valid Coins");
% Refine the edge mask and create valid coin mask
se_dilate = strel('disk', 25, 0);
fb = imfill(faceEdgeMask, 'holes');
Bw2 = imdilate(fb, se_dilate);
validCoinMask = Bw2 & testcoinMask;
se_final = strel('disk', 2, 0);
validCoinMask = imdilate(validCoinMask, se_final);
% Display comparison
montage({testcoinMask, validCoinMask});
title("testcoinMask vs ValidCoinMask");
% Count the number of each type of coin
coinSizes = regionprops('table', validCoinMask, 'Area');
nDimes = nnz(coinSizes.Area < 1100);
nNickels = nnz(coinSizes.Area >= 1100 & coinSizes.Area < 2200);
nQuarters = nnz(coinSizes.Area >= 2200 & coinSizes.Area < 3200);
nFiftyCents = nnz(coinSizes.Area >= 3200);
% Calculate the total USD value
USD = (nDimes * 0.10) + (nNickels * 0.05) + (nQuarters * 0.25) + (nFiftyCents * 0.50);
% Display the total value
disp(['Total USD Value: $', num2str(USD)]);
function [testcoinMask, MaskedtestCoin] = segmentCoin(X)
X = im2gray(X);
% Adjust the threshold value as needed
testcoinMask = X > 150;
% Refine mask with morphological operations
radius = 20; % Adjust this value if necessary
se = strel('disk', radius);
testcoinMask = imclose(testcoinMask, se);
testcoinMask = imfill(testcoinMask, 'holes');
MaskedtestCoin = X;
MaskedtestCoin(~testcoinMask) = 0;
end
0 Comments
krishnaveni
on 31 Aug 2024
testImageIdx = randi([1,3])
testCoinImage = imread("testCoinImage"+testImageIdx+".png");
% Display the original image
imshow(testCoinImage);
title("Original Coin Image");
% Segment the coin from the image
[testcoinMask, MaskedtestCoin] = segmentCoin(testCoinImage);
% Perform morphological operations on the mask
se = strel('disk', 20, 0);
testCoinMask = imfill(testcoinMask, 'holes');
testCoinMask = imerode(testCoinMask, se);
% Apply Gaussian filtering and edge detection
imgFilt = imgaussfilt(MaskedtestCoin, 0.5, 'Padding', "circular", 'FilterDomain', "frequency", 'FilterSize', 3);
faceEdgeMask = edge(imgFilt, "sobel", 0.05, "both");
% Apply the edge mask to the coin mask
faceEdgeMask(~testCoinMask) = false;
imshow(faceEdgeMask);
title("Edge Mask Detection for Valid Coins");
% Refine the edge mask
see = strel("disk", 25, 0);
fb = imfill(faceEdgeMask, "holes");
Bw2 = imdilate(fb, see);
% Create a valid coin mask
validCoinMask = Bw2 & testCoinMask;
set = strel("disk", 2, 0);
validCoinMask = imdilate(validCoinMask, set);
% Display the masks
montage({testCoinMask, validCoinMask});
title("testcoinMask vs ValidCoinMask");
% Calculate coin sizes and classify them
coinSizes = regionprops(validCoinMask, 'Area');
% Initialize counters
nDimes = 0;
nNickels = 0;
nQuarters = 0;
nFiftyCents = 0;
% Define area thresholds for different coins
areaThresholds = struct('Dime', [0, 1100], 'Nickel', [1100, 2200], 'Quarter', [2200, 3200], 'FiftyCent', [3200, Inf]);
% Classify coins based on area
for k = 1:length(coinSizes)
area = coinSizes(k).Area;
if area > areaThresholds.Dime(1) && area <= areaThresholds.Dime(2)
nDimes = nDimes + 1;
elseif area > areaThresholds.Nickel(1) && area <= areaThresholds.Nickel(2)
nNickels = nNickels + 1;
elseif area > areaThresholds.Quarter(1) && area <= areaThresholds.Quarter(2)
nQuarters = nQuarters + 1;
elseif area > areaThresholds.FiftyCent(1)
nFiftyCents = nFiftyCents + 1;
end
end
% Calculate total USD
USD = (nDimes * 0.10) + (nNickels * 0.05) + (nQuarters * 0.25) + (nFiftyCents * 0.50);
% Display results
disp(['Number of Dimes: ', num2str(nDimes)]);
disp(['Number of Nickels: ', num2str(nNickels)]);
disp(['Number of Quarters: ', num2str(nQuarters)]);
disp(['Number of Fifty Cents: ', num2str(nFiftyCents)]);
disp(['Total USD: $', num2str(USD)]);
% Function for segmenting coins
function [testcoinMask, MaskedtestCoin] = segmentCoin(X)
% Convert to grayscale
X = im2gray(X);
% Create a binary mask based on intensity
testcoinMask = X > 150;
radius = 12;
decomp = 4;
se = strel('disk', radius, decomp);
testcoinMask = imclose(testcoinMask, se);
% Mask the coin from the image
MaskedtestCoin = X;
MaskedtestCoin(~testcoinMask) = 0;
end
0 Comments
This question is locked.
See Also
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!