Extract rotated object from a white background

前端 未结 1 540
傲寒
傲寒 2021-01-26 09:49

I have an image with a white background and trying to extract the object within it using MATLAB. I tried different techniques (bounded box) but I am not getting desired results.

相关标签:
1条回答
  • 2021-01-26 09:55

    I propose the following workflow:

    1. Binarize the image
    2. Get the centroid and orientation of the main object
    3. Crop the image to set the center of the object at the center of the image
    4. Rotate the object with respect to the center to compensate for the tilt
    5. Crop again to get the object

    In practice, step 1 turned out to be rather complicated to perform because of the shadow and of the not-so-well-defined boundaries between the white part of the object and the background. The trick I used relies on the fact that, because of the many details inside the object (and the jpg compression) there is a lot of "noise" all over it. So looking for edges combined with a BW-dilation produced a very decent binarized image. I then used regioprops to filter the small outliers and get the properties of the object.

    Here is the code:

    % --- Load image
    Img = imread('Tilted.jpg');
    
    % --- Binarisation
    
    % Find edges and dilate to get a bloc
    BW = edge(mean(Img,3),'sobel');
    BW = imdilate(BW, strel('disk',5));
    
    % Get BW image
    RP = regionprops(BW, 'Area', 'PixelIdxList', 'Centroid', 'Orientation');
    [~, i] = max([RP(:).Area]);
    BW = Img(:,:,1)*0;
    BW(RP(i).PixelIdxList) = 1;
    x = RP(i).Centroid(1);
    y = RP(i).Centroid(2);
    theta = -RP(i).Orientation;
    
    % imshow(BW)
    % plot(x+[0 500*cos(theta*pi/180)], y+[0 500*sin(theta*pi/180)]);
    % return
    
    % --- First crop
    w = min(x-1, size(Img,2)-x);
    h = min(y-1, size(Img,1)-y);
    C = Img(ceil(y-h):floor(y+h), ceil(x-w):floor(x+w),:);
    
    % --- Rotate image
    R = imrotate(C, theta);
    R(R==0) = 255;
    
    % --- Second crop
    
    % Parameters (to adjust)
    th = 70;
    margin = 25; 
    
    % Remove grey levels
    Rwg = std(double(R),0,3).^2;
    
    % Get x-bounds
    sx = sum(Rwg,1);
    x1 = max(find(sx>prctile(sx,th), 1, 'first')-margin, 1);
    x2 = min(find(sx>prctile(sx,30), 1, 'last')+margin, size(Rwg,1));
    
    % Get y-bounds
    sy = sum(Rwg,2);
    y1 = max(find(sy>prctile(sy,th), 1, 'first')-margin, 1);
    y2 = min(find(sy>prctile(sy,th), 1, 'last')+margin, size(Rwg,1));
    
    Res = R(y1:y2, x1:x2, :);
    
    % --- Display
    imshow(Res)
    

    Of course, if you have many different images to process this may not work every time. This code is only a starting point and you now have to modify it to meet your precise needs.

    Best,

    0 讨论(0)
提交回复
热议问题