use*_*729 5 matlab image-processing
x轴的单位是小时(h
),总共有24小时.
y轴的单位是数百万(m
).
如何以图像为单位计算图像中红色曲线下面积m*h
?
重要更新
只有图像可用(而不是数据),我想以编程方式计算区域.
这是一个有趣的解决方案:).顺便说一句,它使用bwfill
(类似于imfill
)需要一些用户交互.
%# Constants
gray_value_curve = 2;
gray_value_box = 3;
area_box_in_units = 10;
%# Read the image
I = imread('C:\p23\graph.gif');
%# Find the area of a unit block
figure(1);
imshow(I,[]);
[BS sq_elem] = bwfill;
imshow(BS,[]);
%# Get the dimensions to make the estimate more accurate
X = zeros(size(BS));
X(sq_elem) = 1;
s = regionprops(X,'Area','BoundingBox');
block_area = s.Area + 2*(s.BoundingBox(3)-1) + 2*(s.BoundingBox(4)-1) + 4;
%#Find the area under the curve
I( ~(I == gray_value_curve | I == gray_value_box) ) = 0;
figure(2);
imshow(I,[]);
[BA area_curve_elem] = bwfill;
imshow(BA,[]);
%# Area under the curve
curve_area = numel(area_curve_elem);
%# Display the area in the required units
area = area_box_in_units*curve_area/block_area;
disp(area);
Run Code Online (Sandbox Code Playgroud)
113.5259
Run Code Online (Sandbox Code Playgroud)
图1
图2
创建全自动解决方案的困难在于,它需要您将有关要处理的输入图像的某些假设硬编码到解决方案中。如果这些假设不适用于您可能遇到的所有潜在图像,则全自动解决方案将不会给出值得信赖的结果,并且尝试扩展全自动解决方案以处理所有可能的输入可能会导致其膨胀难以理解且复杂的代码。
当对输入图像特征的可变性有疑问时,像Jacob这样带有一些用户交互的解决方案通常是最好的。如果您可以确定输入图像的特征遵循一组严格的规则,那么可以考虑自动化解决方案。
作为示例,下面是我编写的一些自动代码,用于估算图表中红色曲线下的面积。由于我使用上图作为指导,因此必须满足许多条件才能使其发挥作用:
根据输入图像的上述条件,可以使用以下代码来近似红色曲线下的面积,而无需用户输入:
[img,map] = imread('original_chart.gif'); %# Read the indexed image
[r,c] = size(img); %# Get the image size
redIndex = find((map(:,1) == 1) & ... %# Find the red index value
(map(:,2) == 0) & ...
(map(:,3) == 0))-1;
greenIndex = find((map(:,1) < 1) & ... %# Find the green index value
(map(:,2) == 1) & ...
(map(:,3) < 1))-1;
blueIndex = find((map(:,1) == 0) & ... %# Find the blue index value
(map(:,2) == 0) & ...
(map(:,3) == 1))-1;
redLine = (img == redIndex); %# A binary image to locate the red line
greenLine = (img == greenIndex); %# A binary image to locate the grid lines
blueLine = (img == blueIndex); %# A binary image to locate the axes lines
w = mean(diff(find(sum(greenLine,1) > r/2))); %# Compute unit square width
h = mean(diff(find(sum(greenLine,2) > c/2))); %# Compute unit square height
squareArea = w*h; %# Compute unit square area
[maxValue,maxIndex] = max(redLine); %# Find top edge of red line
x = find(maxValue > 0); %# Find x coordinates of red line
y = maxIndex(maxValue > 0); %# Find y coordinates of red line
[maxValue,maxIndex] = max(sum(blueLine,2)); %# Find row index of x axis
y = maxIndex-y; %# Zero the y coordinate
totalArea = trapz(x,y)/squareArea; %# Compute the area under the curve
Run Code Online (Sandbox Code Playgroud)
给出以下结果:
squareArea = 460.6 square pixels
totalArea = 169.35 m*h
Run Code Online (Sandbox Code Playgroud)
解释:
我将详细说明计算中涉及的步骤w
:
greenLine
使用函数SUM对二值图像沿每列求和,给出一个1-by-c
向量,其中每个元素是图像每列中有多少网格线像素的计数。r/2
(图像行数一半)的元素表示图像中包含垂直网格线的列。使用函数FIND可以找到这些列的索引。计算 时h
,唯一的区别是沿每一行求和r/2
并替换为c/2
(图像中列数的一半)。