Sunday 31 July 2016

Finding zebra-like pattern in image (Detection of structured-light fringe centerline from photo)


I'm working in a project where fringes are projected against a subject, and a photo is taken. The task is to find the centerlines of the fringes, which represent, mathematically, the 3D curve of intersection between the fringe plane and the subject surface.


The photo is a PNG (RGB), and former attempts used grayscaling then difference thresholding to get a black-and-white, "zebra-like" photography, from which it was easy to find the midpoint of each pixel column of each fringe. The problem is that, by thresholding and also by taking the mean height of a discrete pixel column, we're having some precision loss and quantization, which is not desired at all.


My impression, by looking at the images, is that the centerlines could be more continuous (more points) and smoother (not quantized) if they were detected directly from the non-thresholded image (either RGB or grayscale), by some statistical sweeping method (some flooding / iterative convolution, whatever).


Below is an actual sample image:


enter image description here


Any suggestion would be much appreciated!




Answer



I suggest the following steps:



  1. Find a threshold to separate the foreground from the background.

  2. For each blob in the binary image (one zebra stripe), for each x, find the weighted center (by pixel intensity) in y direction.

  3. Possibly, smooth the y values, to remove noise.

  4. Connect the (x,y) points by fitting some kind of curve. This article might help you. You can also fit a high-level polynomial, though it is worse, in my opinion.


Here is a Matlab code that shows steps 1,2 and 4. I skipped the automatic threshold selection. Instead I chose manual th=40:


These are the curves that are found by finding the weighted average per column: enter image description here



These are the curves after fitting a polynomial: enter image description here


Here is the code:


function Zebra()
im = imread('http://i.stack.imgur.com/m0sy7.png');
im = uint8(mean(im,3));

th = 40;
imBinary = im>th;
imBinary = imclose(imBinary,strel('disk',2));
% figure;imshow(imBinary);

labels = logical(imBinary);
props =regionprops(labels,im,'Image','Area','BoundingBox');

figure(1);imshow(im .* uint8(imBinary));
figure(2);imshow(im .* uint8(imBinary));

for i=1:numel(props)
%Ignore small ones
if props(i).Area < 10
continue

end
%Find weighted centroids
boundingBox = props(i).BoundingBox;
ul = boundingBox(1:2)+0.5;
wh = boundingBox(3:4);
clipped = im( ul(2): (ul(2)+wh(2)-1), ul(1): (ul(1)+wh(1)-1) );
imClip = double(props(i).Image) .* double(clipped);
rows = transpose( 1:size(imClip,1) );
%Weighted calculation
weightedRows = sum(bsxfun(@times, imClip, rows),1) ./ sum(imClip,1);

%Calculate x,y
x = ( 1:numel(weightedRows) ) + ul(1) - 1;
y = ( weightedRows ) + ul(2) - 1;
figure(1);
hold on;plot(x,y,'b','LineWidth',2);
try %#ok
figure(2);
[xo,yo] = FitCurveByPolynom(x,y);
hold on;plot(xo,yo,'g','LineWidth',2);
end

linkaxes( cell2mat(get(get(0,'Children'),'Children')) )
end
end

function [xo,yo] = FitCurveByPolynom(x,y)
p = polyfit(x,y,15);
yo = polyval(p,x);
xo = x;
end

No comments:

Post a Comment

readings - Appending 内 to a company name is read ない or うち?

For example, if I say マイクロソフト内のパートナーシップは強いです, is the 内 here read as うち or ない? Answer 「内」 in the form: 「Proper Noun + 内」 is always read 「ない...