提取图像中的曲线并用于计算(MATLAB)

目的

应小姐姐所邀
原因是小姐姐拿到供应商的一张图表,但是没有具体的数值,更糟糕的是她还想对图中的几条曲线求和。。。。
在这个提供了一种使用matlab提取曲线的方式;

思路

1、首先根据图表颜色筛选出曲线的像素点坐标(彩色图像)
2、根据图像的像素和实际标注额尺寸进行坐标变换;
3、将较宽的曲线求均值(将曲线做细)
4、补充曲线被打断或者遮挡的部分(差值);
5、最后进行更复杂的运算,这里只做了求和。

图是这样的
提取图像中的曲线并用于计算(MATLAB)_第1张图片
提取到的图是这样的
提取图像中的曲线并用于计算(MATLAB)_第2张图片

最终效果是这样的(因为后面的曲线完全重合了,可以直接幅值就行,这里没有处理,后面有机会再加吧。。。)
提取图像中的曲线并用于计算(MATLAB)_第3张图片
程序如下

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('求和后的曲线');

你可能感兴趣的:(matlab,matlab,图像处理,计算机视觉)