应小姐姐所邀
原因是小姐姐拿到供应商的一张图表,但是没有具体的数值,更糟糕的是她还想对图中的几条曲线求和。。。。
在这个提供了一种使用matlab提取曲线的方式;
1、首先根据图表颜色筛选出曲线的像素点坐标(彩色图像)
2、根据图像的像素和实际标注额尺寸进行坐标变换;
3、将较宽的曲线求均值(将曲线做细)
4、补充曲线被打断或者遮挡的部分(差值);
5、最后进行更复杂的运算,这里只做了求和。
最终效果是这样的(因为后面的曲线完全重合了,可以直接幅值就行,这里没有处理,后面有机会再加吧。。。)
程序如下
clc;clear;
close all;
% 读图
pic = imread("pic.jpg");
[m,n,p] = size(pic);
figure,imshow(pic);
imgr = pic(:,:,1);
imgg = pic(:,:,2);
imgb = pic(:,:,3);
% 图表的起始和终止像素
xsta = 22;
ysta = 65;
xsto = 368;
ysto = 768;
% 图表的像素比例
rangex = 1/(xsto-xsta);
rangey = 700/(ysto-ysta);
indexr = [];
indexg = [];
indexb = [];
cntr = 0;
cntg = 0;
cntb = 0;
% 按照颜色提取像素点
for num1 = xsta:xsto
for num2 = ysta:ysto
if imgr(num1,num2)<100 && imgg(num1,num2)<100
mid = [num1,num2];
indexb = [indexb;mid];
cntb = cntb+1;
end
if imgb(num1,num2)<100 && imgg(num1,num2)<100
mid = [num1,num2];
indexr = [indexr;mid];
cntr = cntr+1;
end
if imgb(num1,num2)<100 && imgr(num1,num2)<100
mid = [num1,num2];
indexg = [indexg;mid];
cntr = cntr+1;
end
end
end
% 变换坐标,使横纵坐标对称
value.bx = (indexb(:,2)-ysta)*rangey+300;
value.by = abs((indexb(:,1)-xsta)*rangex-1);
value.rx = (indexr(:,2)-ysta)*rangey+300;
value.ry = abs((indexr(:,1)-xsta)*rangex-1);
value.gx = (indexg(:,2)-ysta)*rangey+300;
value.gy = abs((indexg(:,1)-xsta)*rangex-1);
figure,plot(value.bx,value.by,'b.');
hold on,plot(value.rx,value.ry,'r.');
plot(value.gx,value.gy,'g.');
% 由于线条较粗,单个数值占用了好几个像素,所以需要将曲线细化(这里取的像素点均值)
sta = 350;
sto = 800;
ave.bx = [];
ave.by = [];
ave.gx = [];
ave.gy = [];
ave.rx = [];
ave.ry = [];
for cir = sta:sto
posr = find(round(value.rx) == cir);
if isempty(posr)
continue;
else
ave.rx = [ave.rx cir];
ave.ry = [ave.ry mean(value.ry(posr))];
end
posg = find(round(value.gx) == cir);
if isempty(posg)
continue;
else
ave.gx = [ave.gx cir];
ave.gy = [ave.gy mean(value.gy(posg))];
end
posb = find(round(value.bx) == cir);
if isempty(posb)
continue;
else
ave.bx = [ave.bx cir];
ave.by = [ave.by mean(value.by(posb))];
end
end
strangePoint = find(ave.gx == 383);
ave.gy(strangePoint) = (ave.gy(strangePoint-1)+ave.gy(strangePoint+1))/2;
figure,plot(ave.bx,ave.by,'b',ave.gx,ave.gy,'g',ave.rx,ave.ry,'r');
% 蓝色和绿色曲线有被红色曲线切断的地方,这里做了差值补齐缺失点,便于后续对应不同横坐标对齐,然后求和
wl = sta:1:sto;
rline = interp1(ave.rx,ave.ry,wl);
gline = interp1(ave.gx,ave.gy,wl);
bline = interp1(ave.bx,ave.by,wl);
figure,subplot(2,1,1),plot(wl,rline,'r',wl,gline,'g',wl,bline,'b');
title('提取的三条曲线');
subplot(2,1,2),plot(wl,rline+gline+bline,'k');
title('求和后的曲线');