簡體   English   中英

如何使用MATLAB計算圖像中曲線下的面積?

[英]How do I calculate the area under a curve in an image with MATLAB?

alt text http://internationalpropertiesregistry.com/Server/showFile.php?file=%2FUpload%2Fstatistics.gifc49ca28823a561a41d09ef9adbb5e0c5.gif

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);

產量

113.5259

圖1 替代文字 圖2 替代文字

創建全自動解決方案的難點在於,它需要您將有關您要處理的輸入圖像的某些假設硬編碼到解決方案中。 如果這些假設不適用於您可能遇到的所有潛在圖像,那么全自動解決方案將無法提供值得信賴的結果,並且嘗試擴展全自動解決方案以處理所有可能的輸入可能會導致其膨脹一段難以理解和復雜的代碼。

當關於你的輸入圖像的特征的變化疑問,像一個解決方案雅各的 一些用戶交互通常是最好的。 如果你能肯定的你的輸入圖像的特征遵循一套嚴格的規則,那么自動化解決方案可以考慮。

作為一個例子,下面是我編寫的一些自動代碼,用於近似圖表中紅色曲線下的區域。 由於我使用上面的圖表作為指南,因此它必須滿足一些條件才能工作:

  • 繪制線的紅色像素必須在圖像中唯一地描述為包含等於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的步驟:

  1. 使用函數SUM沿着每列對二進制圖像greenLine求和,給出1-by-c向量,其中每個元素是圖像的每列中有多少網格線像素的計數。
  2. 此向量的元素大於r/2 (圖像中行數的一半)表示包含垂直網格線的圖像列。 使用函數FIND找到這些列的索引。
  3. 使用函數DIFF找到這些列索引之間的成對差異。 這給出了一個包含網格線之間空間寬度(以像素為單位)的向量。
  4. 最后,函數MEAN用於計算圖像中所有網格線之間的空間的平均寬度。

計算h ,唯一的區別是沿每行執行求和, r/2替換為c/2 (圖像中列數的一半)。

由於您只有圖像可用,我建議您通過眼睛進行整合:計算紅線下方的整個方塊的數量。

對於紅線相交的每個方格,根據線下方的數量決定是否將其包含在計數中。 不要試圖估計紅線下面有多少正方形,最多會給你一個更准確的幻覺。

編輯:我為你計算了綠色方塊,答案是168 mh

由於這似乎不是你可以整合的“功能”,我會使用數值積分技術。 我總是偏向於使用“ 梯形規則 ”進行數值積分的trapz

就像是:

area = trapz(data);

應該足夠了。

希望有所幫助,

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM