Гистограмма «уровня черных чернил» изображения по горизонтальной оси

У меня есть файл черно-белого изображения (или PDF), и я хочу получить гистограмму горизонтального профиля изображения. То есть для каждого столбца в изображении я хочу получить сумму значений оттенков серого для пикселей в столбце. Если изображение имеет размер X на Y пикселей, я получу числа X от 0 (для полностью черного столбца) до 255 * Y (для полностью белого столбца).

Пожалуйста, смотрите вторую панельэтот комикс

Мне бы хотелось, чтобы гистограмма была такой, но каждая ячейка представляла бы все «черные чернила» на изображении с этой координатой x (пикселем).

Будучи бедным аспирантом, я вынужден использовать только командную строку Linux, программы FOSS (ImageMagick, gnuplot, Perl, g ++ и т. Д.). Что-то вроде GIMP будет полезно, только если я смогу запустить команду через терминал, поскольку у меня не будет доступа к графическому интерфейсу. Файл визуального вывода будет полезен на потом, но не обязателен.

Кто-нибудь знает, как я могу извлечь эту информацию? Поиски «профиля изображения» просто приводят к информации о цветовых профилях.

 andyras31 окт. 2012 г., 02:22
Окей круто. Какую ОС вы используете?
 user171782831 окт. 2012 г., 00:58
Если это бесплатно, я могу получить это. Я пытался изучать Python несколько лет назад, но ни один из синтаксисов не застрял без чего-либо для работы; это может быть мой первый проект (набравpython берет меня к>>> незамедлительный).
 andyras31 окт. 2012 г., 00:55
У вас есть Python (и модуль Image)?

Ответы на вопрос(1)

Решение Вопроса

используя две мои любимые бесплатные утилиты: python и gnuplot.

Как соискатель (вычислительный) аспирант, я советую, что если вы хотите делать что-то бесплатно, Python является одним из самых универсальных инструментов, которые вы можете научиться использовать.

Вот скрипт Python, который выполняет первую часть, считая значение в градациях серого (от 0 для белого до 255 для черного):

#!/usr/bin/python

import Image            # basic image processing/manipulation, just what we want

im = Image.open('img.png')       # open the image file as a python image object
with open('data.dat', 'w') as f: # open the data file to be written
    for i in range(im.size[0]):  # loop over columns
        counter = sum(im.getpixel((i,j)) for j in range(im.size[1]))
        f.write(str(i)+'\t'+str(counter)+'\n')  # write to data file

Шокирующе безболезненно! Теперь, чтобы gnuplot составил гистограмму *:

#!/usr/bin/gnuplot

set terminal pngcairo size 925,900
set output 'plot.png'
#set terminal pdfcairo
#set output 'plot.pdf'
set multiplot

## first plot
set origin 0,0.025              # this plot will be on the bottom
set size 1,0.75                 # and fill 3/4 of the whole canvas

set title "Black count in XKCD 'Self-Description'"
set xlabel 'Column'
set ylabel "Black\ncount" norotate offset screen 0.0125

set lmargin at screen 0.15      # make plot area correct size
set rmargin at screen 0.95      # width = 740 px = (0.95-0.15)*925 px

set border 0                    # these settings are just to make the data
set grid                        # stand out and not overlap with the tics, etc.
set tics nomirror
set xtics scale 0.5 out 
set ytics scale 0

set xr [0:740]                  # x range such that there is one spike/pixel

## uncomment if gnuplot version >= 4.6.0
## this will autoset the x and y ranges
#stats 'data.dat'
#set xr [STATS_min_x:STATS_max_x+1]
#set yr [STATS_min_y:STATS_may_y]

plot 'data.dat' with impulse notitle lc 'black'

## second plot
set origin 0,0.75               # this plot will be on top
set size 1,0.25                 # and fill 1/4 of the canvas

unset ylabel; unset xlabel      # clean up a bit...
unset border; unset grid; unset tics; unset title

set size ratio -1               # ensures image proper ratio
plot 'img.png' binary filetype=png with rgbimage

unset multiplot         # important to unset multiplot!

Чтобы запустить эти сценарии, сохраните их в том же каталоге, где находится изображение, которое вы хотите построить (в данном случае комикс XKCD, который я сохранил какimg.png). Сделайте их исполняемыми. В Баш это

$ chmod 755 grayscalecount.py plot.plt

Затем (если Python + модуль изображения + gnuplot все установлены), вы можете запустить

$ ./grayscalecount.py
$ ./plot.plt

На моем компьютере под управлением Ubuntu 11.10 с gnuplot 4.4.3 я получаю этот классный сюжет в конце:

** Примечание: * Есть много разных гистограмм, которые может сделать gnuplot. Я думал, что этот стиль хорошо демонстрирует данные, но вы можете посмотреть на форматирование ваших данных длягистограммы гнуплота.

Есть много способов заставить Python создавать графики самостоятельно или с помощью gnuplot (matplotlib, pygnuplot, gnuplot-py), но я не настолько легок в этом. Gnuplot отлично подходит для написания сценариев, и есть много способов сделать так, чтобы он прекрасно работал с python, bash, C ++ и т. Д.

 user171782831 окт. 2012 г., 02:44
Вы, сэр, являетесь моделью для сообщества StackOverflow. Я использовал ваш комментарий / подсказку от ранее иХорошая работа Павла с участиемplot "dataFile" using 1 и получил что-то подобное. Спасибо за ваш совет и ваш ясный, пошаговый, консолидированный учебник. Я надеюсь, что вопрос достаточно общий, чтобы привести будущих гуглеров к вашему ответу
 mgilson31 окт. 2012 г., 16:19
@andyras - я выучил ТОННУ классных трюков с питоном, следуяpython тег на StackOverflow - он получает намного больше трафика, чемgnuplot :). Я был также счастлив, когда вы упомянулиpygnuplot выше - хотя недавно я начал играть сmatplotlib немного. Это было бы довольно изящно (не то, чтобы я планировал отказаться от pygnuplot в ближайшее время!)
 andyras31 окт. 2012 г., 03:11
Всегда пожалуйста и добро пожаловать в stackoverflow! Мне было очень весело придумать этот ответ.
 andyras31 окт. 2012 г., 16:14
Спасибо, @mgilson! Вы научили меня нескольким новым вещам о синтаксисе Python, которые действительно делают сценарий более компактным и элегантным. Я обновил свой ответ. Я не думаю, что объекты изображений поддерживают индексирование в стиле numpy, иначе я бы тоже это добавил.
 mgilson31 окт. 2012 г., 15:46
Очень хороший ответ (+1). Я отформатировал ваш код Python, чтобы сделать его совместимым с PEP-8, и использовал диспетчер контекста, чтобы убедиться, что файл корректно сбрасывается (Ваш старый способ не гарантировал, что все данные действительно будут в файле при выходе из программы, потому что Вы не закрыли файл). Я бы посоветовал использованиеsum также удалить внутреннюю петлю:sum(im.getpixel((i,j)) for j in range(im.size[1])), Еслиim поддержка NumPy, как индексирование,sum(im[i,:]) также будет работать (но я не знаю об этом, так как я обычно не используюImage).

Ваш ответ на вопрос