суббота, 4 августа 2018 г.

Оцифровка функции с картинки

Задача. У Вас есть спектр, график функции на картинке (фотографии) в статье или книжке. Требуется перевести его в цифровой вид для дальнейшей обработки. 
Например, хочется перевести в цифру распределение частиц с картинки ниже.
Устанавливаем программу engauge-digitizer - interactively extracts numbers from bitmap graphs or maps:
sudo apt-get install engauge-digitizer
Запускаем engauge. Импортируем изображение. На изображении указываем 3 точки для задания координат: (0, 0), (0, 16), (70, 0). Они обозначены красными крестиками. 
Программа engauge пробует сама найти сегменты кривых (нужно нажать пиктограмму с зеленой полоской). Удерживая Shift выделяем мышью все относящиеся к делу сегменты. Появляются синие крестики - оцифрованные точки кривой. Сохраняем файл, экспортируем данные в формат *.CSV. 
Я предпочитаю рисовать графики программой Gnuplot, потому подправляю исходный текстовый файл CSV до такого:
#x Curve1
2.31405 0.20000
2.97521 0.714777
3.30579 1.2646
...
Теперь можно нарисовать график. Однако, дальнейшая работа с данными может оказаться не совсем удобной, так как точек хотя и достаточно для рисунка, но мало для дальнейшего математического анализа. Поможет простой рецепт, код на Octave:
[a,b] = textread("srep20589-f1.csv","%f %f","headerlines",1);
N = 1024;
xi = linspace(min(a),max(a),N)';
yi = griddatan(a,b,xi);
Так мы сделали равномерную сетку по \(x\) и увеличили линейной интерполяцией число точек до 1024.
На происхождение данных всё еще указывает зубчатый характер графика, видный при увеличении. Воспользуемся преобразованием Фурье для сглаживания кривой.
n=[-N/2:N/2]; n(N+1) = []; freq = n./N;
% построим фильтр, отсекающий высокие частоты
b_order = 10; w_c = 0.01;
w = sqrt(1./(1+(freq./w_c).^b_order))';
w = fftshift(w);
и сравним результаты до и после фильтрации:
hold on
plot(xi, yi)
plot(xi, ifft(fft(yi).*w))

Комментариев нет:

Отправить комментарий