从白色背景中提取旋转对象
Extract rotated object from a white background
我有一张白色背景的图像,并尝试使用 MATLAB 提取其中的对象。我尝试了不同的技术(边界框),但没有得到想要的结果。我已经尝试过这个 Whosebug post 但它不是很有效:MATLAB Auto Crop
如何提取对象?知道哪种技术合适吗?
图片如下:
我提出以下工作流程:
- 二值化图像
- 获取主要对象的质心和方向
- 裁剪图像以将对象的中心设置在图像的中心
- 相对于中心旋转对象以补偿倾斜
- 再次裁剪得到对象
实际上,由于阴影和物体白色部分与背景之间的边界不太明确,因此第 1 步执行起来相当复杂。我使用的技巧依赖于这样一个事实,即由于对象内部的许多细节(以及 jpg 压缩),它上面有很多 "noise"。因此,寻找边缘与 BW 膨胀相结合产生了非常不错的二值化图像。然后我使用 regioprops
过滤小的异常值并获取对象的属性。
代码如下:
% --- 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)
当然,如果您有很多不同的图像要处理,这可能不会每次都有效。此代码只是一个起点,您现在必须对其进行修改以满足您的具体需求。
最佳,
我有一张白色背景的图像,并尝试使用 MATLAB 提取其中的对象。我尝试了不同的技术(边界框),但没有得到想要的结果。我已经尝试过这个 Whosebug post 但它不是很有效:MATLAB Auto Crop
如何提取对象?知道哪种技术合适吗?
图片如下:
我提出以下工作流程:
- 二值化图像
- 获取主要对象的质心和方向
- 裁剪图像以将对象的中心设置在图像的中心
- 相对于中心旋转对象以补偿倾斜
- 再次裁剪得到对象
实际上,由于阴影和物体白色部分与背景之间的边界不太明确,因此第 1 步执行起来相当复杂。我使用的技巧依赖于这样一个事实,即由于对象内部的许多细节(以及 jpg 压缩),它上面有很多 "noise"。因此,寻找边缘与 BW 膨胀相结合产生了非常不错的二值化图像。然后我使用 regioprops
过滤小的异常值并获取对象的属性。
代码如下:
% --- 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)
当然,如果您有很多不同的图像要处理,这可能不会每次都有效。此代码只是一个起点,您现在必须对其进行修改以满足您的具体需求。
最佳,