poster
2019-12-10, 20:41
替代文字http://internationalpropertiesregistry.com/Server/showFile.php?file=%2FUpload%2Fstatistics.gifc49ca28823a561a41d09ef9adbb5e0c5.gif (http://internationalpropertiesregistry.com/Server/showFile.php?file=%2FUpload%2Fstatistics.gifc49ca28823a561a41d09ef9adbb5e0c5.gif)
x轴的单位为小时( h ),总共有24小时。
y轴的单位为百万( m )。
如何以m*h为单位计算图像中红色曲线下方的面积?
重要更新
只有图像很容易获得(没有数据),我想以编程方式计算面积。
回答:
创建全自动解决方案的困难在于,这将要求您将有关要处理的输入图像的某些假设硬编码到解决方案中。如果这些假设不能满足您可能遇到的所有潜在图像,则全自动解决方案将无法提供可信赖的结果,而尝试扩展全自动解决方案以处理所有可能的输入可能会导致其膨胀难以理解和复杂的代码混乱。
当关于你的输入图像的特征的变化疑问,像一个解决方案雅各的 (https://stackoverflow.com/questions/2973973/how-do-i-calculate-the-area-with-matlab-unit-mh/2975223#2975223) 一些用户交互通常是最好的。如果可以确定输入图像的功能遵循一组严格的规则,则可以考虑使用自动解决方案。
例如,下面是我编写的一些自动代码,用于近似估算图中红色曲线下的面积。由于我使用上图作为指导,因此必须满足许多条件才能使其工作:
绘制线的红色像素必须在图像中唯一描述为包含等于0的绿色和蓝色分量和等于1的红色分量。
网格线的绿色像素必须在图像中唯一地描述为包含小于1的红色和蓝色分量以及等于1的绿色分量。
轴线上的蓝色像素必须在图像中唯一地描述为包含等于0的红色和绿色分量和等于1的蓝色分量。
网格线和轴线必须始终在水平或垂直方向上完全对齐。
网格线的长度必须跨越图像宽度和高度的一半。
x轴必须是图像中最长的水平蓝线。
网格线必须始终为1像素粗。
根据输入图像上的上述条件,可以使用以下代码来近似红色曲线下的区域,而无需用户输入:
[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 得到以下结果:
squareArea = 460.6 square pixels totalArea = 169.35 m*h
说明:
我将详细介绍计算w涉及的步骤:
使用函数SUM (http://www.mathworks.com/access/helpdesk/help/techdoc/ref/sum.html)沿每一列对二进制图像greenLine求和,得到一个1-by-c向量,其中每个元素是图像的每一列中有多少个网格线像素的计数。
此向量的元素大于r/2 (图像中的行数的一半)表示包含垂直网格线的图像列。这些列的索引可使用函数FIND (http://www.mathworks.com/access/helpdesk/help/techdoc/ref/find.html)找到。
这些列索引之间的成对差异可通过函数DIFF (http://www.mathworks.com/access/helpdesk/help/techdoc/ref/diff.html)找到。这给出了一个矢量,其中包含网格线之间的间隔的宽度(以像素为单位)。
最后,函数MEAN (http://www.mathworks.com/access/helpdesk/help/techdoc/ref/mean.html)用于计算图像中所有网格线之间的平均间距。
在计算h ,唯一的区别是沿每一行执行求和,并且将r/2替换为c/2 (图像中的列数减半)。
更多&回答... (https://stackoverflow.com/questions/2973973)
x轴的单位为小时( h ),总共有24小时。
y轴的单位为百万( m )。
如何以m*h为单位计算图像中红色曲线下方的面积?
重要更新
只有图像很容易获得(没有数据),我想以编程方式计算面积。
回答:
创建全自动解决方案的困难在于,这将要求您将有关要处理的输入图像的某些假设硬编码到解决方案中。如果这些假设不能满足您可能遇到的所有潜在图像,则全自动解决方案将无法提供可信赖的结果,而尝试扩展全自动解决方案以处理所有可能的输入可能会导致其膨胀难以理解和复杂的代码混乱。
当关于你的输入图像的特征的变化疑问,像一个解决方案雅各的 (https://stackoverflow.com/questions/2973973/how-do-i-calculate-the-area-with-matlab-unit-mh/2975223#2975223) 一些用户交互通常是最好的。如果可以确定输入图像的功能遵循一组严格的规则,则可以考虑使用自动解决方案。
例如,下面是我编写的一些自动代码,用于近似估算图中红色曲线下的面积。由于我使用上图作为指导,因此必须满足许多条件才能使其工作:
绘制线的红色像素必须在图像中唯一描述为包含等于0的绿色和蓝色分量和等于1的红色分量。
网格线的绿色像素必须在图像中唯一地描述为包含小于1的红色和蓝色分量以及等于1的绿色分量。
轴线上的蓝色像素必须在图像中唯一地描述为包含等于0的红色和绿色分量和等于1的蓝色分量。
网格线和轴线必须始终在水平或垂直方向上完全对齐。
网格线的长度必须跨越图像宽度和高度的一半。
x轴必须是图像中最长的水平蓝线。
网格线必须始终为1像素粗。
根据输入图像上的上述条件,可以使用以下代码来近似红色曲线下的区域,而无需用户输入:
[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 得到以下结果:
squareArea = 460.6 square pixels totalArea = 169.35 m*h
说明:
我将详细介绍计算w涉及的步骤:
使用函数SUM (http://www.mathworks.com/access/helpdesk/help/techdoc/ref/sum.html)沿每一列对二进制图像greenLine求和,得到一个1-by-c向量,其中每个元素是图像的每一列中有多少个网格线像素的计数。
此向量的元素大于r/2 (图像中的行数的一半)表示包含垂直网格线的图像列。这些列的索引可使用函数FIND (http://www.mathworks.com/access/helpdesk/help/techdoc/ref/find.html)找到。
这些列索引之间的成对差异可通过函数DIFF (http://www.mathworks.com/access/helpdesk/help/techdoc/ref/diff.html)找到。这给出了一个矢量,其中包含网格线之间的间隔的宽度(以像素为单位)。
最后,函数MEAN (http://www.mathworks.com/access/helpdesk/help/techdoc/ref/mean.html)用于计算图像中所有网格线之间的平均间距。
在计算h ,唯一的区别是沿每一行执行求和,并且将r/2替换为c/2 (图像中的列数减半)。
更多&回答... (https://stackoverflow.com/questions/2973973)