Сложность создания полностью автоматизированного решения заключается в том, что вам потребуется жестко закодировать в своем решении определенные предположения о входных изображениях, которые вы собираетесь обрабатывать. Если эти предположения не соответствуют всем потенциальным изображениям, с которыми вы можете столкнуться, полностью автоматизированное решение не даст достоверных результатов, и попытка расширить полностью автоматизированное решение для обработки всех возможные входные данные, вероятно, приведут к тому, что он превратится в непонятный и сложный беспорядок кода.
Если вы сомневаетесь в вариативности функций ваших входных изображений, лучше всего подойдет решение, например Джейкоба с некоторым взаимодействием с пользователем. Если вы можете быть уверенными в том, что функции ваших входных изображений следуют строгому набору правил, тогда можно рассмотреть автоматизированное решение.
В качестве примера ниже приведен некоторый автоматизированный код, который я написал, чтобы приблизить область под красной кривой на вашем графике. Поскольку я использовал приведенный выше график в качестве руководства, для его работы необходимо выполнить ряд условий:
- Красные пиксели нанесенной линии должны быть однозначно описаны на изображении как содержащие зеленые и синие цветовые компоненты, равные 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
:
- Бинарное изображение
greenLine
суммируется по каждому столбцу с помощью функции SUM , давая вектор 1-by-c
, где каждый элемент представляет собой количество пикселей линии сетки в каждом столбце изображения. .
- Элементы этого вектора, которые больше
r/2
(половина числа строк в изображении) указывают столбцы изображения, которые содержат вертикальную линию сетки. Индексы этих столбцов находятся с помощью функции НАЙТИ .
- Попарные разности между этими индексами столбцов находятся с помощью функции DIFF . Это дает вектор, содержащий ширину (в пикселях) пробелов между линиями сетки.
- Наконец, функция MEAN используется для вычисления средней ширины промежутков между всеми линиями сетки на изображении.
При вычислении h
единственное отличие состоит в том, что сумма выполняется по каждой строке и r/2
заменяется на c/2
(половина числа столбцов в изображении).