how can I remove the black mask from the image?

5 vues (au cours des 30 derniers jours)
Abdelrahman Sheham
Abdelrahman Sheham le 14 Nov 2018
Modifié(e) : DGM le 5 Jan 2023

Réponses (1)

DGM
DGM le 5 Jan 2023
Modifié(e) : DGM le 5 Jan 2023
I'm sure there are multiple ways to approach this, but here's one. In this case, the rectangle is clearly darker than the rest of the entire image. Given that, the ROI can be isolated by simple thresholding to create a mask.
Once we have a mask that describes the dark region, we can observe the relationship between adjacent pixels local to the edge of the rectangle. If we can assume that the image is smooth, it's a fair bet that two adjacent pixels should have similar values. Clearly they don't, but by observing how they differ, we can determine the value transformation that has been applied to make the region darker.
In this example, I create two masks which select 1px-wide strips along the long edges of the rectangle. Ideally, you'd do the same along the short edges so as to have a larger sample size, but that's just more verbose. The long edges suffices here. Polyfit() can easily do a simple linear fit on the sampled subvectors, and polyval() can apply it to the pixels in the ROI.
inpict = imread('esrectangle.jpg');
% find the rectangle by simple thresholding
rectmask = inpict < 90;
rectmask = bwareafilt(rectmask,1);
imshow(rectmask)
% generate row masks inside and outside the long rectangle edges
inmask = ~imerode(rectmask,ones(1,3)) & rectmask;
outmask = imdilate(rectmask,ones(1,3)) & ~rectmask;
% extract those pixels and do a simple linear fit
y = double(inpict(inmask));
x = double(inpict(outmask));
%P = polyfit(y,x,1); % polyfit works fine
P = robustfit(y,x); P = flipud(P); % but this is a bit more consistent
% adjust the ROI according to the fit
outpict = inpict;
outpict(rectmask) = polyval(P,double(outpict(rectmask)));
imshow(outpict)
All that's left are the JPG artifacts that surrounded the sharp edge. It should be noted that those artifacts are also limiting our ability to get an accurate estimation of the transformation. Still, the result is close enough.
Now let's say the rectangle wasn't well-separated by value alone. Could it be separated other ways? You might try doing some sort of adaptive thresholding, or if you can rely on the ROI having strong grid-aligned edges, you can simply find the edges. Here's one way.
inpict = imread('esrectangle.jpg');
% calculate the gradient magnitude
G = imgradient(inpict);
imshow(G,[])
% find the rectangle edges in G
edgemask = G > 200; % i chose this threshold by observation
% try to guard against both spurs and pits on the interior edges
% this will tend to create spurs on exterior corners, but that's okay
Ex = medfilt2(edgemask,[20 1]);
Ey = medfilt2(edgemask,[1 20]);
edgemask = Ex | Ey;
% convert edge mask to a rectangle mask
rectmask = imdilate(imclearborder(~edgemask),ones(3));
% now we have the same rectangle mask that we did before
imshow(rectmask)
At this point, we're back to the rectangle mask, and the prior example can be applied.

Community Treasure Hunt

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

Start Hunting!

Translated by