How to recognize 6 colors of a face rubik's cube at the same time?

12 views (last 30 days)
  2 Comments
DGM
DGM on 15 Oct 2022
Will all the images have the object consistently positioned within the frame?
Will it always be the same cube and lighting?
You might be able to try sampling regions within each square, finding their average colors, and then trying to find the closest match between the observed colors and a list of known colors.
If the object position or lighting changes a lot, things might get complicated.
Sang
Sang on 15 Oct 2022
I understand your problem but I don't know what the command is

Sign in to comment.

Answers (3)

DGM
DGM on 15 Oct 2022
Edited: DGM on 15 Oct 2022
Let's start with an example that doesn't solve the problem. Herein, I extract the mean color in each block. Much of this example (the figures) is purely for illustration and wouldn't be necessary in practice. All you need is a correctly ordered color table.
% start with the image
Argb = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1157503/image.jpeg');
% create a mask that samples the centers of the blocks
% stdfilt() is used to find regions of contrast (boundaries of blocks)
% this image is thresholded to create a rough low-contrast region mask
% the image is trimmed and padded with zero to detatch blobs from the border
se = ones(100,1);
blockmask = max(stdfilt(Argb,ones(21)),[],3) < 10;
blockmask = padarray(blockmask(2:end-1,2:end-1),[1 1],0,'both');
% imopen() is used with a long strel to cut the blocks apart
% doing it this way is sensitive to image rotation
% erosion shrinks the mask to exclude regions near block edges
% bwareafilt() gets rid of any remaining small blobs
blockmask = imopen(imopen(blockmask,se),se');
blockmask = imerode(blockmask,ones(25));
blockmask = bwareafilt(blockmask,9);
% this is the mask
imshow(blockmask)
% segment the mask and the source image
% CT is a color table containing the mean color in each mask blob
CC = bwconncomp(blockmask);
nblocks = CC.NumObjects;
CT = zeros(nblocks,3);
Act = reshape(Argb,[],3);
for b = 1:nblocks
pixidx = CC.PixelIdxList{b};
sampledpixels = Act(pixidx,:);
CT(b,:) = mean(sampledpixels,1)/255;
end
% get the centroids of all the blobs
S = regionprops(CC,'centroid');
C = vertcat(S(:).Centroid);
% display indicators on the mask
% note that blobs aren't ordered as expected
clf
imshow(blockmask)
for b = 1:nblocks
text(C(b,1),C(b,2),sprintf('%d',b),'color','k','fontsize',20)
end
% try to snap the centers to a grid
% again, this assumes the image isn't severely rotated/distorted
climits = [min(C,[],1); max(C,[],1)];
Cnom = round((C-climits(1,:))./range(climits,1)*2 + 1);
% reorder color samples and centroids
idx = sub2ind([3 3],Cnom(:,2),Cnom(:,1));
CT(idx,:) = CT;
C(idx,:) = C;
% display indicators on the mask after sorting
% now the block information is in column-major order
clf
imshow(blockmask)
for b = 1:nblocks
text(C(b,1),C(b,2),sprintf('%d',b),'color','k','fontsize',20)
end
% display colored patches on the original image
% this shows that the sample colors correspond to the blocks
clf
imshow(Argb); hold on
hs = scatter(C(:,1),C(:,2),5000,CT,'filled');
hs.MarkerEdgeColor = 'k';
% so this is the color table for this image
CT
CT = 9×3
0.0490 0.7965 0.1848 0.1900 0.4245 0.7063 0.8080 0.7477 0.1320 0.9248 0.3623 0.4214 0.8225 0.8080 0.8325 0.9897 0.5775 0.3256 0.9105 0.3310 0.3839 0.0045 0.7953 0.1136 0.9107 0.8509 0.1033
Okay, so now you have a color table. Now what? At this point, you'd have to try to classify the colors. Since I only have one image, I really don't have anything to test against. You might take a few pictures and build a reference table from the average of similar-class samples. Then you can do distance minimization to find which reference color matches a given image under test.
This answer includes a similar process. Similarly, rgb2ind() could be used as well.
If you can provide other images, i might be able to expand on this, otherwise it's up to you to work with the images you're receiving.
  24 Comments
Image Analyst
Image Analyst on 28 Oct 2022
You must have a version older than r2018b, when imsplit was introduced. So you can do
hsvImage = rgb2hsv(Auncropped);
H = hsvImage(:, :, 1);
S = hsvImage(:, :, 2);
V = hsvImage(:, :, 3);
DGM
DGM on 28 Oct 2022
Do you have an older version (R2018a or older), or do you not have IPT? If you don't have IPT, there will be other issues. If you're running something significantly older than R2018x, there may be other version-dependent issues that may show up.
If the only issue is the lack of imsplit(), you can use the attached file to replace it. MIMT splitchans() can do everything IPT imsplit() does, and should not be dependent on anything. You'll obviously have to change that line to call splitchans() instead of imsplit().

Sign in to comment.


Image Analyst
Image Analyst on 15 Oct 2022
There are lots of ways to "solve" this but it depends on what you want to know? Do you want to know only how many colors there are? Do you want to know the predicted reference color for every pixel in the image? Do you want to find each cube face and find the dominant color for that cube face?
What I'd to is to classify every pixel in the image into one of your six known reference colors. For example you could use the attached demo to use discriminant analysis (see attached demo) or K nearest neighbors (see attached demo), or you could convert to LAB color space and find the lowest delta E color difference like I did in this link https://www.mathworks.com/matlabcentral/answers/1819405-how-to-change-the-color-of-each-pixel-in-a-masked-image#comment_2410068 for a poster who was comparing a melanoma spot to 6 reference colors.

Image Analyst
Image Analyst on 19 Oct 2022
I think you need to do it this way. It holds the Guinness Book of World's record for the fastest Rubik solution ever:

Community Treasure Hunt

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

Start Hunting!