Задать вопрос

Как из изображения графика вытащить координаты?

Есть графики двух видов.
graphCompare.php?graphType=0&graphID%5B%
fr.png

Как вытащить координаты (вида [x, y]), никогда не занимался этим, но сложности не остановят, ибо нужно очень.

На чем (в чем) это быстрее всего можно будет реализовать? Какой алгоритм?
  • Вопрос задан
  • 7911 просмотров
Подписаться 5 Оценить 2 комментария
Решения вопроса 1
Если быстро и на коленке то:
1) подготавливаем специальным образом изображения удаляя ненужныю информацию:



и



2) получаем значения граничных линий сетки, цвета сетки и графиков для подготовленных изображений:
по x: 10 и 10000, по y: -25 и 10, сетка rgb(221,221,221), график rgb(0,0,255)
по x: 30 и 10000, по y: 90 и 132, сетка rgb(104,104,104), график rgb(150,255,0)

3) на питоне с помощью PIL пишем код который будет получать по предоставленным данным координаты:
# -*- coding: utf-8 -*-

from math import log10, fabs
import Image


def check_pixel_colour(pixel, colour, delta=(0,0,0)):
    '''сравниваем цвет пиксиля с эталонным цветом с погрешностью дельта'''
    return (colour[0] - delta[0]) <= pixel[0] <= (colour[0] + delta[0]) and\
           (colour[1] - delta[1]) <= pixel[1] <= (colour[1] + delta[1]) and\
           (colour[2] - delta[2]) <= pixel[2] <= (colour[2] + delta[2])


def better_colour_value(pixels, colour):
    '''из списка цветов выбираем более подходящий эталонному цвету'''
    delta = 1024
    better_pixel = None
    for pixel in pixels:
        current_delta = fabs(pixel[0] - colour[0]) +\
                        fabs(pixel[1] - colour[1]) +\
                        fabs(pixel[2] - colour[2])
        if current_delta < delta:
            delta = current_delta
            better_pixel = pixel
    return better_pixel


def get_border_grids(image, grid_colour):
    '''
    получаем номера пиксилей по оси x первой и последней линий сетки, по оси y верхней и нижней
    данные пиксили соответствуют переданным граничным значениям сетки
    '''
    width, height = image.size
    for x in xrange(width):
        if check_pixel_colour(image.getpixel((x, 0)), grid_colour):
            yield x
            break
    for x in xrange(width - 1, -1, -1):
        if check_pixel_colour(image.getpixel((x, 0)), grid_colour):
            yield x
            break
    for y in xrange(height - 1, -1, -1):
        if check_pixel_colour(image.getpixel((0, y)), grid_colour):
            yield y
            break
    for y in xrange(height):
        if check_pixel_colour(image.getpixel((0, y)), grid_colour):
            yield y
            break


def get_linear_value(x, x1, x2, x1_value, x2_value):
    '''получаем значение для текущего пикселя с учетом граничных значений сетки для линейной оси'''
    k = (x2 - x1) / (x2_value - x1_value)
    b = x1 - k * x1_value
    return (x - b) / k


def get_log_value(x, x1, x2, x1_value, x2_value):
    '''получаем значение для текущего пикселя с учетом граничных значений сетки для логорифмической оси'''
    k = (x1 - x2) / (log10(x1_value) - log10(x2_value))
    b = x1 - k * log10(x1_value)
    return 10**((x - b) / k)


def process_graph(image_path, x1_value, x2_value, y1_value, y2_value, colour, delta, grid_colour):
    '''получаем список координат графика на изображении'''
    image = Image.open(image_path)
    width, height = image.size
    x1, x2, y1, y2 = get_border_grids(image, grid_colour)
    coordinates = []

    for x in xrange(width):
        pixels = {}
        for y in xrange(height):
            pixel = image.getpixel((x, y))
            if check_pixel_colour(pixel, colour, delta):
                pixels[pixel] = y
        if len(pixels) > 0:
            y = pixels[better_colour_value(pixels.keys(), colour)]
            x_value = get_log_value(x, x1, x2, x1_value, x2_value)
            y_value = get_linear_value(height - y, height - y1, height - y2, y1_value, y2_value)
            coordinates.append((x_value, y_value))

    return coordinates


if __name__ == '__main__':
    print process_graph('test_001.png', 10., 10000., -25., 10., (0,0,255), (10,10,50), (221,221,221))
    print process_graph('test_002.png', 30., 10000., 90., 132., (150,255,0), (50,50,10), (104,104,104))



4) запускаем программу и получаем результаты для каждого пикселя по ox
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
GavriKos
@GavriKos
Какая то странная формулировка задачи… Что значит вытащить координаты? Координаты чего? График — это графическое представление некой функции, или массива пар х, у. Вам нужно весь массив вытащить? Или зная х получить y?
Ответ написан
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
1) определить в пикселях поле где расположен граффик
2) задать масштаб (сколько пикселей приходится на одну еденицу значения)
3) идем по полю и ищем зеленую или синию линии (пиксели) и помечаем координаты в массив (идти только нужно по вертикали, при поиске точек на графике)
Ответ написан
m08pvv
@m08pvv
Если график в программе, то гораздо точнее и надёжнее (но, возможно сложнее, а возможно и проще) будет выдрать данные прямо из программы.
Ответ написан
Комментировать
@leggiermente
Я как-то использовал g3data. Результат не очень удовлетворил. Но для простых графиков подойдёт.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы