extract colored image from white background

7 views (last 30 days)
Ali Asad
Ali Asad on 20 Feb 2015
Edited: DGM on 28 May 2023
i have an image(file attached) with white background and trying to extract it using MATLAB. I tried different techniques (bounded box) but not getting desired results. here is the code which i tried http://stackoverflow.com/questions/24135462/matlab-auto-crop
How i can extract image? any idea which technique is suitable?

Answers (1)

DGM
DGM on 28 May 2023
Edited: DGM on 28 May 2023
Checks are (usually) some light pastel color. Sometimes they'll have a helpful dark border, but other times (like this case, they'll be partially white. Imaging the object against an similarly-colored background is setting yourself up for problems. I know you didn't design the flatbed scanner to be that color, but it can be changed, and there are good reasons for changing it.
First, let's try to do this the hard way.
inpict = imread('check.jpg');
% strip color, flatten image
outpict = im2gray(inpict);
outpict = imbothat(outpict,ones(11));
% rotate image based on content
R = radon(outpict);
[~,idx] = max(max(R,[],1));
angle = 90-(idx-1);
outpict = imrotate(outpict,angle,'bilinear');
% try to find the object
% this is not at all robust
mask = outpict > 4; % haha like that'll ever work twice
mask = bwareafilt(mask,1); % routing # will probably tend to get cut off
S = regionprops(mask,'boundingbox');
imshow(mask,'border','tight')
% crop the output
% this is the gray, flattened image, ready for processing
outpict = imcrop(outpict,S.BoundingBox);
imshow(outpict,'border','tight')
% or if you want to start over with a colored, unflattened image
outpict = imrotate(inpict,angle,'bilinear');
outpict = imcrop(outpict,S.BoundingBox);
imshow(outpict,'border','tight')
On the other hand, let's say you stuck a sheet of black craft paper, felt, or PVA foam to the scanner lid instead. This example image is not perfectly black. It's dark gray with the same dust and nonuniformity that was present in the prior image.
inpict = imread('checkblack.jpg');
% strip color
graypict = im2gray(inpict);
% create mask
mask = imbinarize(graypict); % this could be more elaborate if you want
mask = imfill(mask,'holes');
mask = bwareafilt(mask,1);
imshow(mask,'border','tight') % we can actually get a good mask!
% since the mask is good, we can rotate mask based on mask properties
S = regionprops(mask,'minferetproperties','boundingbox');
angle = S.MinFeretAngle-90;
[mask rect] = imcrop(mask,S.BoundingBox); % crop to reduce area
mask = imrotate(mask,angle,'nearest'); % align to grid
S = regionprops(mask,'boundingbox'); % find ROI
% apply same transformations to the image and crop it
outpict = imcrop(inpict,rect);
outpict = imrotate(outpict,angle,'bilinear');
outpict = imcrop(outpict,S.BoundingBox); % final crop
imshow(outpict,'border','tight')
Not only is this more robust, it's significantly faster. It could probably be simplified further.
In the first example, we can't rely on subject-background contrast to tell us where the object edges are. Without that assurance, and the assumption that the subject can be presented in any location or orientation, we have to make some huge leaps of faith that will almost certainly fail. We have to rely on the text/lines being bold enough to give us the dominant orientation peaks. If the checks have some sort of large scale pattern, that could easily ruin our ability to find the orientation. For example:
We have to rely on subtle shadows and text contrast to avoid cutting off the routing number. I should point out that when I say "subtle", I mean that the object edges differ from the local background by only a few LSBs in a lot of places.
In the second example, we used a dead-simple change to the physical imaging setup to help ensure that we have good subject-background contrast. That means that we can more reliably get a mask that cleanly isolates the subject. We can get orientation information directly from the mask without needing to rely on any of the internal feature contrast (e.g. text,lines) of the object.
There is one other minor benefit to scanning things on a black background, and that's simply that it reduces print-through. If you're scanning on a white background, you may find that scans of a double-sided print tend to be polluted with the faint image of the text on the backside of the page. It probably doesn't matter for checks, but it's one thing to consider. Plenty of scanners actually come with black covers instead of white, but white has its advantages too.
  2 Comments
Image Analyst
Image Analyst on 28 May 2023
My guess is he's trying to simulate what happens when someone uses a smartphone banking app to deposit a check, so he wouldn't have control over the image capture conditions. The user places the check down and snaps a picture of it with the bank's app. The check is supposed to be on a uniform background, but of course end-users can't follow directions so the app must be robust enough to either find the check regardless of the cluttered background, or alert the user that there is not a uniform background surrounding the check and to resnap the image on a uniform background.
DGM
DGM on 28 May 2023
Edited: DGM on 28 May 2023
I kind of thought that might be the case, but it was a dead question, so I was silently banking (ha ha) on nobody requiring an answer to "how do I segment any check in any position on any background in any lighting conditions".
It's not a mountain I was willing to climb out of my own curiosity. Without clear constraints on the image presentation, it sounds like either a fool's errand or a large-scale project that nobody would do for free. I imagine any robust solution would need to verify the routing number, etc are readable before accepting the shot. I don't have any OCR tools anyway.
Checks probably have some standardized features that could help, but I wrote this answer while my network was out, so I didn't get to research that.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!