Please show the original image.
If the background behind the cards is a different color than the cards, like black background and white cards, then you can simply threshold, call imfill, and label then use ismember to create a mask for each card.
backgroundMask = ...
allCardsMask = imfill(~backgroundMask, 'holes');
allCardsMask = bwareafilt(allCardsMask, 3);
labeledImage = bwlabel(allCardsMask);
cardMask1 = ismember(allCardsMask, 1);
cardMask2 = ismember(allCardsMask, 2);
cardMask3 = ismember(allCardsMask, 3);
Your edge detection method could have a lot of problems if your edges are not completely connected, like in the upper right corner of your card on the right.
To identify the cards, you might use SIFT but a simpler way might be to simply count the number of colored pixels on each card in each color channel. It could be that every card has a unique count for R, G, and B. Then you could simply look up that number in a lookup table that you've filled up in advance with the "official" counts for each card. This would probably be far simpler than SIFT or SURF.