<p>八度音阶的完整工作实现:</p>
<pre><code>pkg load image
pkg load signal
median_filter_size = 10;
min_vertical_distance_between_layers = 35;
min_bright_level = 100/255;
img_rgb = imread("oct.png");% it's http://i.stack.imgur.com/PBnOj.png
img = im2double(img_rgb(:,:,1));
img=medfilt2(img,[median_filter_size median_filter_size]);
function idx = find_max(img,col_idx,min_vertical_distance_between_layers,min_bright_level)
c1=img(:,col_idx);
[pks idx]=findpeaks(c1,"MinPeakDistance",min_vertical_distance_between_layers,"MinPeakHeight",min_bright_level);
if ( rows(idx) < 2 )
idx=[1;1];
return
endif
% sort decreasing peak value
A=[pks idx];
A=sortrows(A,-1);
% keep the two biggest peaks
pks=A(1:2,1);
idx=A(1:2,2);
% sort by row index
A=[pks idx];
A=sortrows(A,2);
pks=A(1:2,1);
idx=A(1:2,2);
endfunction
layers=[];
idxs=1:1:columns(img);
for col_idx=idxs
layers=[layers find_max(img,col_idx,min_vertical_distance_between_layers,min_bright_level)];
endfor
hold on
imshow(img)
plot(idxs,layers(1,:),'r.')
plot(idxs,layers(2,:),'g.')
my_range=1:columns(idxs);
for i = my_range
x = idxs(i);
y1 = layers(1,i);
y2 = layers(2,i);
if y1 > rows(img_rgb) || y2 > rows(img_rgb) || x > columns(img_rgb) || y1==1 || y2==1
continue
endif
img_rgb(y1,x,:) = [255 0 0];
img_rgb(y2,x,:) = [0 255 0];
endfor
imwrite(img_rgb,"dst.png")
</code></pre>
<p>其思想是将图像的每一列处理为一条曲线(灰度级),并寻找两个峰值,每个峰值都在一个图层的边界上。在</p>
<p>输入图像是由OP:<a href="https://i.stack.imgur.com/PBnOj.png" rel="nofollow noreferrer">http://i.stack.imgur.com/PBnOj.png</a><a href="https://i.stack.imgur.com/PBnOj.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/PBnOj.png" alt="enter image description here"/></a>链接的原始图像</p>
<p>代码保存为<code>"dst.png"</code>的图像如下:</p>
<p><a href="https://i.stack.imgur.com/LiAWa.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/LiAWa.png" alt="enter image description here"/></a></p>