Так получилось, что фотография, это мой основной профессиональный вид деятельности, а программирование — хобби, которое иногда позволяет размять мозг. Кроме непосредственно разминки для мозга, программирование помогает и в работе. Например, писал полезные штуки, такие как это или это, или это.

Недавно поставил себе задачу, как бы еще порадовать своих клиентов. Вспомнил многочисленные просьбы клиентов на свадебную съемку: «Как хорошо было бы, если бы на банкете вы смогли показать коротенькое слайдшоу из фотографий, которые отсняли за день». На эти просьбы приходилось отказывать, по нескольким причинам: лень таскать с собой ноутбук для сборки слайдшоу, нет времени на отбор пары десятков снимков из сотен, из raw опять же нужно конвертировать, и самое главное — на это все нужно время, которого нет.

Это рассказ, о том, как мне удалось сделать для себя инструмент, который с минимальным моим участием и минимальным дополнительным весом в рюкзаке, помогает сделать красивые слайдшоу. И конечно же рассказ о python, ffmpeg и linux на android.

Неожиданный выбор железа


Первая проблема — это лишний вес. Мне нужен был полноценный linux на достаточно приличном железе. Изначально мой выбор пал на Orange PI PC, о котором я услышал на гигтаймсе. Железка была заказана и доставлена. Мне казалось, это то что нужно — 4 ядра по 1.5 ггц, 1 гб оперативной памяти и полноценные USB. Но на деле, лишний раз убедился, что без нормальной поддержки, все «клоны raspberry», ничего не стоят. Очень глючные образы OS, постоянно отваливающиеся ядра под нагрузкой, проблема с работой библиотек, чтоб, например подключить lcd дисплей.
И самое главная проблема, это неожиданный killed, при свободных 800 мб оперативки, на участке кода типа:
from PIL import Image
img=Image.new('RGB',(6000,4000)) #на деле мне нужно было не создавать, а открывать фотографии
img.rotate()

Причем тоже самое прекрасно работало на нетбуке с 1гб оперативке без свопа, а так же на Raspberry PI первом. И уж тем более, и речи не могло быть, чтоб делать тоже самое, но на 4-х ядрах одновременно.

Решение пришло неожиданно, когда я взял в руки смартфон, чтоб прочитать пришедшее сообщение:
А в кармане то постоянно лежит железка с 2.2 ггц 4-х ядерным процессором, 2гб оперативном памяти + USB-otg имеется (Nexus 5). Осталось найти способ полноценного запуска Linux окружения. После отбрасывания различных вариантов с перепрошивкой (хотелось пользоваться им полноценно и как смартфоном), выход был найден — Linux Deploy. Если кратко, Linux Deploy запускает полноценное linux окружение в chroot'e (подробнее о программе можно почитать в блоге у нашего соотечественника — разработчика), и самое главное для меня — монтировать произвольный каталог из fs android в свое окружение. Без этого, не была бы возможна работа с картридером SD карт памяти, воткнутым в OTG разъем.

Отбор фотографий


Слайдшоу из сотен фотографий, заняло бы пару часов времени. Нужен был способ легко и быстро отобрать 20-40 фотографий. Пролистывать даже 100 фотографий со смартфона — то еще удовольствие, а количество может доходить к вечеру до тысячи (дубли с серийной съемки, брак, пристрелочные фото, репортаж и пр.)
Взглянув на фотоаппарат, вспомнил про кнопку, которой никогда не пользовался — спасительницей оказалась кнопка «rate», которая присваивает рейтинг фотографии:



Колесом прокрутки справа достаточно быстро пролистываются снимки, и на нужном нажимается кнопка «rate». Так как ты уже знаешь, что удачного за сегодня отснял, на все уходит не больше пары минут. Остается заставить программу найти и выбрать те снимки, которым присвоен хоть какой нибудь рейтинг.

Так как рейтинг попадает в exif, понадобится замечательный пакет exiftool (sudo apt-get install libimage-exiftool-perl) и wrapper к нему для python. А дальше все просто:

import os
import exiftool
all_files=[]

"""проходимся по всем файлам на SD карте """
for directory, dirnames, filenames in os.walk(PATH_TO_SD_ROOT):    
	for name in filenames:
		f=os.path.join(directory, name)
			if f.lower().endswith('.cr2') or f.lower().endswith('.jpg'): #и добавляем в список jpg и raw файлы
				all_files.append(f)
	tool=exiftool.ExifTool()  
	tool.start() #запускаем exiftool

        # просим пройтись по нашему списку и выдать рейтинги
	result=tool.get_tags_batch(['XMP:Rating'],all_files)
	rated_files=[]
	for x in result:
		if x['XMP:Rating']>0:
			rated_files.append(x['SourceFile'])
# на выходе получаем список нужных нам файлов
rated_files.sort()


Следующий этап достаточно тривиален — копирование нужных фотографий во временный каталог и резайс в несколько потоков для дальнейшей работы. Единственное, на чем бы хотел заострить внимание, это raw, в который я снимаю. Конвертацией занимается утилита dcraw (хотя это не полноценная конвертация, а лишь выдергивание вшитой jpg в raw файл, но в данном случае, это более чем достаточно.

import subprocess

for n,x in enumerate(self.rated_files):
	dcraw_opts = ["dcraw", "-e", "-c", x]    # -e - вытащить вшитый jpg, -с выдать нам его в stdout
	dcraw_proc = subprocess.Popen(dcraw_opts, stdout=subprocess.PIPE)		
	image = StringIO.StringIO(dcraw_proc.communicate()[0])  # берем фотографию со stdout
	image.seek(0)
	open('input/%02d.jpg'%(n),'wb').write(image.read()) # и записываем в нужное место.


Сделай мне красиво!



На предыдущем этапе можно было бы остановиться, взяв фотографии и пустив их как слайдшоу на ноутбуке диджея, подключенного к проектору, но хочется, чтоб все это выглядело красиво.
На помощь приходит такая замечательная вещь, как ffmpeg (avconv). Я не любитель каких либо ярких спецэффектов, мне достаточно легкой динамики, в виде zoom'a фотографии и «crossfade» перехода между слайдами. Скажу сразу, несмотря на огромные возможности ffmpeg, это сделать у меня не получилось. Например, фильтр zoompan, выдавал ужасное качество и дрожащую картинку. После недели, проведенные за чтением мануалов и форумов, решено было сделать это «в лоб»:

def processImage(numb):
	img=Image.open('input_temp/%02d.jpg'%numb) # открываем текущее изображение
        # для эффекта crossfade открывает следущее изображение, или если оно последнее, создаем пустое
	try:next_img=Image.open('input_temp/%02d.jpg'%(numb+1)).resize((1280,720),Image.ANTIALIAS)
	except:next_img=Image.new('RGB',(1280,720),'black')

        # чтобы не захламлять память сотнями отдельных кадров, попросим ffmpeg принимать на stdin фотографии
        # и получим на выходе готовый отрезок видео
	p = subprocess.Popen(['avconv', '-y', '-f', 'image2pipe', '-vcodec', 'mjpeg', '-r', '25', '-i', '-', '-vcodec', 'mjpeg','-q:v', '3' , '-r', '25', 'output/%02d.mjpg'%(numb)], stdin=subprocess.PIPE)


	# 100 кадров при 25 к/c - 4 секунды видео на слайд
	for x in xrange(100):
                # при каждой итерации делаем кроп исходной фотографии в соответствии с пропорцией 16:9
		n=img.crop((int(float(x)*16.0/9.0),x,int(1920.0-float(x)*16.0/9.0),1080-x))
                # и делаем резайс к конечному размеру
		n=n.resize((1280,720),Image.ANTIALIAS)
                # на третей секунде, начинаем "подмешивать" следующую фотграфию
		if x>75:
			n=Image.blend(n,next_img,float(x-75)/25)

                # и скармливаем ffmpeg'у
		n.save(p.stdin,'JPEG')
	p.stdin.close()
	p.wait()


Ах да, я что то там говорил про ядра процессора. Хотелось бы распаралеллить этот процесс, чтоб были заняты все ядра. В python это делается очень очень просто:
from multiprocessing import Pool
s=len(glob.glob('input_temp/*.jpg')) #берем количество фотографий 
pool = Pool()
pool.map(processImage, xrange(s)) # и отдаем их воркерам, количество которых будет равно количеству ядер процессора
pool.close()
pool.join()


В итоге мы имеем множество отрезков mjpeg видео, которые нужно соединить воедино, вставив музыку.
Погуглив, не нашел лучшего способа, как сначала напрямую соединить видео, используя cat:
cat 00.mjpg 01.mjpg ..... > out.mjpg

Осталось только переконвертировать его в нужный формат, добавив музыку:
avconv -threads 4 -framerate 25 -i out.mjpg  -i  audio.mp3  -shortest -y  -r 25  -preset veryfast out.mp4


Чтобы не возиться каждый раз в консоли, а нужно было выбирать музыкальный трек, вписывать название для слайдшоу (для первого кадра) и пр, поднял простой web сервер, который стартует при запуске Linux Deploy. Я использовал простенький фреймворк bottle. Выглядит это вот так:



Итого


2-3 минуты отбор фотографий, запуск Linux Deploy, localhost в браузере, пару секунд на то, чтоб вписать title и нажать на СТАРТ. Далее 10-15 минут работы смартфона, и видео готово:



Таким же способом можно делать не только слайдшоу из фотографий, но и склеивать видео: пометить нужные отрывки в камере кнопкой rate и склеить их потом ffmpeg'ом.

И небольшой анонс

Если эта тема окажется интересной, я сделаю еще несколько публикаций. Например, на очереди статья, как сделать вот такую милую и функциональную фотобудку:

Комментарии (72)


  1. Quiensabe
    21.01.2016 07:01
    +6

    Здорово! Действительно очень элегантное решение!

    А не планируете опубликовать исходники? Понятно, что в статье ключевые моменты освещены, но хотелось бы, так сказать, «комплект»… Чтобы сразу начать эксперименты.

    Еще небольшое замечание. Возможно это уже у меня проф.деформация, но мне лично очень мешает, что при переходе фотография в начале стоит на месте (во время микса), и только потом начинает двигаться. Это очень легко поправить, но я думаю будет заметно приятнее.

    На счет новых статей — было бы здорово! Про фото-будку — очень интересно. Подписался.


    1. Bringoff
      21.01.2016 16:46

      мне лично очень мешает, что при переходе фотография в начале стоит на месте (во время микса), и только потом начинает двигаться

      Тоже об это глаз каждый раз спотыкался, неплохо бы начинать движение сразу.


    1. JC_Piligrim
      22.01.2016 01:08
      +1

      Подтверждаю, дискомфортно.

      Хорошо будет сделать так, как вы сказали, плюс замедлить скорость зума. Такой быстрый ни к чему, достаточно чтобы в кадре ощущалось лёгкое движение. Можно ещё прикрутить рандомно, чтобы не в центр каждый раз зумилось, а в произвольную рандомную точку, или пойти дальше и алгоритмом распознавания лиц находить центр зуммирования.

      Ах, да, можно ещё виньетирование, помимо зума сделать рандомный/осмысленный сдвиг кадра и всё такое прочее, чтобы «дороже смотрелось». Но это уже advanced-уровень. :)


      1. pcmaniac
        28.01.2016 03:20
        +1

        Вместо распознавания лиц, можно делать зуммирование «умным кропом», он дешевле распознавания лиц и даёт хорошие результаты на фотографиях разного типа, в т.ч. и без лиц.

        Пример работы смарткропа
        image


  1. KorP
    21.01.2016 08:48
    +4

    Вот крайне интересно читать о том, как программирование помогает «обычным людям» в решии их повседневных задач. Хоть цифровая фотография и крайне тесна связана с IT, но большинство фотографов кроме как ФШ да ЛР ничего и не умеют, и даже винду переставить не могут, а тут человек пишет не такое уж и простое ПО для себя. Круто. Автор молодец!!!


    1. aik
      21.01.2016 09:05
      +1

      большинство фотографов кроме как ФШ да ЛР ничего и не умеют, и даже винду переставить не могут


      Умения переустановить винду — это самое важное умение для фотографа, да. :)


      1. KorP
        21.01.2016 09:05

        Нет, это говорит об общей компьютерной грамотности, это лишь яркий показатель


        1. aik
          21.01.2016 09:14
          +1

          Переустановка винды в наше время это настолько простой процесс, что показателем компьютерной грамотности не является. Воткнул диск, да два-три раза нажал «далее». Даже установка какой-нибудь убунты — тоже не показатель грамотности.
          А вот запуск линукса на телефоне и дальнейший запуск там самописной программы — это показатель.


          1. KorP
            21.01.2016 09:16

            Так в том то и дело
            Воткнул диск, да два-три раза нажал «далее»
            а большинство не могут. Это как раз показатель низкой компьютерной грамотности, о чём я и говорил изначально.


            1. aik
              21.01.2016 09:20

              Могут, просто боятся. Или не хотят.
              Но при этом могут быть хорошими фотографами, дизайнерами, бухгалтерами или даже программистами.


    1. snikes
      21.01.2016 09:49

      Самое главное умение фотографа на пк (помимо обработки фото) либо делать backup, либо Raid, второе умение — восстанавливать уделенные фото…


      1. reff
        21.01.2016 12:30

        либо делать backup, либо Raid
        Резервная копия не заменяет RAID-массив и наоборот.


        1. snikes
          21.01.2016 13:05
          +1

          не всегда важен способ главное, чтобы был дубль. Но грамотное приятнее безграмотного. Согласен с Вами.


          1. aik
            21.01.2016 13:41

            Так вот RAID как раз «дублей» и не обеспечивает. От удаленных и испорченных файлов не спасёт.


            1. snikes
              21.01.2016 19:18

              RAID — 1 например спасет от испорченных файлов, либо убийством одного из дисков. От удаления Да — не спасет, но удаление, чаще всего — осознанный шаг


          1. reff
            21.01.2016 16:48

            Удалив файл с массива, Вы удалите и «дубль». Тот же файл останется в резервной копии. Почувствуйте разницу.


    1. kAIST
      21.01.2016 10:47
      +1

      Да у меня скорее нетипичный случай )
      Программировать начал раньше чем фотографировать. В одно время встал выбор, в какую сторону двигаться дальше — приглашали работать программистом в достаточно хорошую компанию, но выбрал фотографию.
      По мелочи тоже здорово помогает. Например, как то надоело ждать, как любимый резайсер фотографий делает все в один поток, написал свой )


    1. pcmaniac
      28.01.2016 03:24

      Работал в студии, где у каждого фотографа была своя, очень некислая рабочая станция, предоставленная фирмой, но всё что касается софта, лежало на плечах фотографов/художников/верстальщиков и их познания в сфере тонкого тюнинга софта и железа меня поражали.


  1. aik
    21.01.2016 09:10
    +1

    В общем, если убрать код, то процесс выглядит так:

    1) На экране фотоаппарата отбираете фото
    2) Карту памяти подключаете к телефону, из отмеченных фото выдергиваете джпеги
    3) Через веб-интерфейс для вашей программы указываете параметры конвертирования, ждёте
    4) На выходе — видеофайл со слайдшоу.

    Так?


    1. kAIST
      21.01.2016 10:27
      +1

      Да, все именно так!


      1. Popik
        21.01.2016 14:46

        А в чем фишка снимать в RAW, а потом дергать оттуда превью джипег?


        1. aik
          21.01.2016 15:52

          Чтобы не расходовать место на джпеги, например.


        1. kAIST
          21.01.2016 16:12

          Слайдшоу в день съемки, это вторично. Главное все же, это фотографии. Для гарантированного результата, нужны raw.
          Вытащить jpeg из raw — простая и быстрая операция. Если бы её не было, то быстрее и проще не стало бы, так как остаётся все остальное.


  1. Meklon
    21.01.2016 09:11
    +3

    Круто, спасибо. Программирование действительно во многих случаях помогает. Я вот Python и OpenCV начал учить. Удивительно, но офигенно полезно для врача-исследователя в лаборатории.


    1. KorP
      21.01.2016 10:48
      +3

      Вот я бы послушал на эту тему, пилите пост :)


      1. Meklon
        21.01.2016 12:48
        +2


        Вот первые робкие шаги) Пока обучаю видеть метки. С python и OpenCV никогда раньше не стлакивался. Пока идет довольно легко. Хотя меня вымораживает неопределенность в типе переменной. Хрен ти что может храниться. То ли контейнер с массивом какой-то фигни, то ли кадр, то ли Boolean. очень легко запутаться и налажать, если переменные плохо названы. Возможно я чего-то не понимаю пока. До этого немного C ковырял.


        1. pcmaniac
          28.01.2016 03:27

          ИМХО было ошибкой одеть рубашку того же цвета, как и метки. Или так и было задумано? :)


          1. Meklon
            28.01.2016 07:13

            Вообще ошибся) но это самое начало. Только сегментация. Я потом ещё фильтры крутил, erode/dilate, определение координат и прочее.


            1. pcmaniac
              28.01.2016 15:22

              Радует глаз когда специалисты нетехнических специальностей так глубоко копают :)
              В штатах это давно норма, когда какой-нибудь бизнес-аналитик пишет свой аналитический софт под конкретные задачи и инструмент тут не важен, видел на Excel таких монстров, что возникал вопрос «и кто тут программист». Мне также приносили задачки типа «Я тут в Access накидал базу, давай сделаем нормальный сетевой вариант?», я открываю это «накидал», и понимаю что это месяцы работы, а приносит это далеко не программист. Важно, что только человек, глубоко знакомый с предметной областью, понимает все тонкости того, что нужно автоматизировать.
              Думаю что скоро к тому придём, что на уровне школы программирование будет преподаваться на уровне иностранных языков.


              1. Meklon
                28.01.2016 15:39

                Спасибо) в итоге, правда, код наполовину из комментариев, чтобы не забыть и все время явно изобретаю велосипед. Хотя работает, да. И не хватает математики и базовых универсальных алгоритмов. Сейчас думаю, как корректнее определить центроид четырёхугольника при наличии координат вершин. Среднее арифметическое (x,y) странно выглядит.


                1. pcmaniac
                  28.01.2016 19:29

                  А в чём собственно проблема? Считаем центроиды четырёх треугольников, проводим к ним линии из противоположных вершин, ищем точки пересечения. Или проблема это именно алгоритмически и эффективно реализовать?


                  1. Meklon
                    29.01.2016 10:56

                    Проблема алгоритмически. Я до сих пор не привыкну к манипуляции массивами точек. Трудно) Вот пока наброски кода. Примитивненько, но мне еще надо учиться:

                    Код
                    # The distance between green marks shuold be at least 4a, where "a" is the width of the square.
                    # It's easier to draw the area around the central point between them.
                    
                    import cv2
                    import numpy as np
                    
                    cap = cv2.VideoCapture(0)
                    
                    def nothing(x):
                        pass
                    
                    cv2.namedWindow('mask')
                    
                    # Create sliders for range adjusting
                    cv2.createTrackbar('Hue_low', 'mask', 40, 255, nothing)
                    cv2.createTrackbar('Hue_high', 'mask', 76, 255, nothing)
                    cv2.createTrackbar('Saturation_low', 'mask', 81, 255, nothing)
                    cv2.createTrackbar('Saturation_high', 'mask', 255, 255, nothing)
                    
                    while True:
                        # flashing the counter
                        centrIndex = 0
                        # init list
                        centroidListX = []
                        centroidListY = []
                    
                        # Take each frame
                        _, frame = cap.read()
                    
                        # Convert BGR to HSV
                        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
                    
                        # Get current slider position
                        Hue_low = cv2.getTrackbarPos('Hue_low', 'mask')
                        Hue_high = cv2.getTrackbarPos('Hue_high', 'mask')
                        Sat_low = cv2.getTrackbarPos('Saturation_low', 'mask')
                        Sat_high = cv2.getTrackbarPos('Saturation_high', 'mask')
                    
                        # define range of green color in HSV
                        lower_green = np.array([Hue_low, Sat_low, 40])
                        upper_green = np.array([Hue_high, Sat_high, 250])
                    
                        # Threshold the HSV image to get only blue colors
                        mask = cv2.inRange(hsv, lower_green, upper_green)
                    
                        #Erode disabled to speedup. Works nice without it.
                        mask = cv2.erode(mask, None, iterations = 1)
                        mask = cv2.dilate(mask, None, iterations = 1)
                    
                        # Bitwise-AND mask and original image
                        image_result = cv2.bitwise_and(frame, frame, mask=mask)
                    
                        # Detecting edges
                        image_mask_blur = cv2.medianBlur(mask, 3)
                        image_canny = cv2.Canny(image_mask_blur, 30, 150)
                    
                        # Closing gaps
                        kernel_canny = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))
                        image_canny_closed = cv2.morphologyEx(image_canny, cv2.MORPH_CLOSE, kernel_canny)
                    
                        # Finding contours
                        (cnts, _) = cv2.findContours(image_canny_closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
                    
                        for c in cnts:
                    
                            # approximate the contour
                            peri = cv2.arcLength(c, True)
                            approx = cv2.approxPolyDP(c, 0.03 * peri, True)
                            # get the bounding box with it's coordinates and aspect ratio
                            (x,y,w,h) = cv2.boundingRect(approx)
                            aspectRatio = w / float(h)
                    
                            # initialize bool variables
                            boolRectangle = False
                            boolPeri = False
                            boolAspect = False
                    
                            if len(approx) >= 4 and len(approx) <= 6:
                                boolRectangle = True
                            if peri >= 50:
                                boolPeri = True
                            if aspectRatio > 0.9 and aspectRatio < 1.1:
                                boolAspect = True
                    
                            if boolRectangle and boolPeri and boolAspect:
                                cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2)
                    
                                # get centroid of rectangle
                                centroidX = x + w/2
                                centroidY = y + h/2
                                centroidListX.append(centroidX)
                                centroidListY.append(centroidY)
                    
                                cv2.circle(frame, (centroidListX[centrIndex], centroidListY[centrIndex]), 1,(0,0,255),3)
                                centrIndex += 1
                    
                                if centrIndex == 4:
                                    centroidMainX = 0
                                    centroidMainY = 0
                                    for loopIndex in range(0, 3):
                                        centroidMainX = centroidMainX + centroidListX[loopIndex]
                                        centroidMainY = centroidMainY + centroidListY[loopIndex]
                                    centroidMainX = centroidMainX/4
                                    centroidMainY = centroidMainY/4
                                    cv2.circle(frame, (centroidMainX, centroidMainY), 5, (0, 0, 255),3)
                                    cv2.rectangle(frame, (centroidMainX - int(peri),centroidMainY + int(peri)), (centroidMainX + int(peri), centroidMainY - int(peri)), (0,255,255), 2)
                            cv2.imshow('frame', frame)
                    
                        # Visualization
                        cv2.imshow('mask', image_result)
                        #cv2.imshow('canny_closed', image_canny_closed)
                        #cv2.imshow('canny', image_canny)
                        k = cv2.waitKey(5) & 0xFF
                        if k == 27:
                            break
                    
                    cv2.destroyAllWindows()
                    
                    


        1. ekungurov
          28.01.2016 22:16

          1. Meklon
            29.01.2016 10:52

            Посмотрю. но я пока на 2.7. Сейчас Ubuntu 14.04 на работе, не хочу сильно ворошить систему вручную. Перейду на 16.04 — обновлюсь.


    1. kAIST
      21.01.2016 10:52
      +2

      Очень приятная штука, когда благодаря программирования, у тебя развязываются руки )


  1. zvyagaaa
    21.01.2016 09:13
    +1

    я может быть напишу глупость, но почему нельзя было сделать то же самое силами самого андроида?


    1. aik
      21.01.2016 09:19

      Привычные инструменты, отсутствие необходимости мусорить в системе, легкий перенос с места на место…


    1. kAIST
      21.01.2016 10:30

      Каким образом? Есть софт, который что то может делать по отдельности, но много ручной работы.
      Приличных программ для создания слайдшоу, например, не нашёл. Все пытаются сделать его квадратным для инстаграма. А уж чтоб сохранить только снимки с рейтингами, да ещё из raw пакетно, никто не умеет.


      1. yktoo
        21.01.2016 11:02
        +1

        Написать код с такой же функциональностью на Java, наверняка там множество готовых библиотек для изображений и видео


        1. kAIST
          21.01.2016 11:06
          +1

          Думаю, проблем написать на Java нет, но рассказ не об этом.
          У меня «одноразовое» решения для личного пользования. Сделал максимально быстрым для себя способом.


        1. zvyagaaa
          21.01.2016 14:33

          Да, я про это и спрашивал, тем более, что опыт программирования у автора есть. Заодно мог бы и продавать продукт, наверняка бы нашлась бы целевая аудитория.


  1. Fromer
    21.01.2016 09:23
    +3

    Игорь, наблюдаю за вашим python-творчеством еще с времен Симбиан и s40 — ваши статьи всегда интересны, пишите еще. Смотря на ваши работы в программировании, вспоминаются слова Advice from an Old Programmer из Learn Python The Hard Way

    ...Programming as a profession is only moderately interesting. It can be a good job, but you could make about the same money and be happier running a fast food joint. You're much better off using code as your secret weapon in another profession.


    1. Shrim
      21.01.2016 10:12
      +1

      Symbian, хорошие были времена. У меня был смартфон, но не было компьютера и я тогда читал Россума (book ods) и писал скрипты прямо на смартфоне, с экраном 174х208, сейчас с трудом себе это представляю. Может и мои работы вам знакомы — MP3Editor, MBM Tool, AIF Tool, GIF Tool. Мы с Игорем тогда общались на димонвидео, можно сказать вместе работали.


      1. kAIST
        21.01.2016 10:42

        Да да, это было трудное, но веселое «детство») Спасибо за то, что сподвиг вообще начать заниматься программированием )


      1. Fromer
        21.01.2016 11:04

        MBM Tool помню — ресурсы менял на своей старенькой Nokia N76, благодаря чему все одногрупники несли свои телефоны на починить и настроить мне. Спасибо вам за нее.


  1. SantaClaus16
    21.01.2016 09:47

    Сразу несколько вопросов:
    1. Сколько уходит зарядки у вашего смартфона на 1 описанный вами цикл.
    2. А если кто нибудь вам позвонит в момент рендера?
    3. Не виснет, не глючит? Прямо все без нареканий?


    1. kAIST
      21.01.2016 10:33

      В момент, когда задействованы 4 ядра на все 100, да, глючит и лагает, на звонок ответить затруднительно. Но это длится минут 10. Да и в это время не до звонков — на съёмках же )
      По поводу заряда, не замерял, но не думаю что уйдёт заряда больше чем за 15-20 минут работы какой нибудь требовательной игрушки.


  1. TimsTims
    21.01.2016 10:01

    Очень круто!

    Только думаю, что все действительно можно соединить в одном полноценном приложении. И что-то мне подсказывает, что такие проги уже есть)

    Вот крайне интересно читать о том, как программирование помогает «обычным людям» в решии их повседневных задач.
    +1 решение проблем — это самый кайф в нашем деле!


    1. kAIST
      21.01.2016 10:36

      Уж очень специфичная штука, чтоб такое приложение уже было ) даже на PC готового нет. По отдельности — пожалуйста, но вот все вместе нет.


      1. Seekeer
        21.01.2016 10:45

        А у вас не было мысли запилить такое приложение? Мне кажется, среди фотографов было бы весьма востребованным.


        1. kAIST
          21.01.2016 10:50

          Тут проблема — кроме питона, мне всегда было лень что то новое изучать (за исключением немного c++ для микроконтроллеров), а распространять приложение в виде скриптов для Linux deploy среди не айтишников, которые почти все на iOS — бесполезно )


  1. ghosthope
    21.01.2016 10:08

    Супер! Делитесь своим опытом, у вас прекрасно получается!!! Спасибо за столько интересный рассказ! Не думали оформить все либой и где-нибудь распространять за не бесплатно?


    1. kAIST
      21.01.2016 10:40

      Спасибо. Нет, не думал. Программирование это хобби, основной доход другой.
      Единственное, что, сделал коммерческий заказ на доработку софтины для коллеги, который занимается видео. Все тоже самое, но половину функционала не понадобилось, так как видео нужно склеивать напрямую, без какой либо обработки.


  1. d7s2di
    21.01.2016 11:05

    Замечательное решение и отличная статья. Частенько вот сталкивался с мнением, де никак фотографу под Linux работать не удастся, мол фотошопа нет и тому подобное. А оно вон как получается, отличная автоматизация рабочего процесса.


    1. kAIST
      21.01.2016 11:11

      Да, но без Windows, если занимаешься коммерческой съемкой, действительно очень сложно. Как раз таки из за фотошопе и тому подобное. Аналоги есть, но до коммерческого применения не дотягивают. С удовольствием поучаствовал бы, например, в работе над dark table, но не хватает времени (


      1. Meklon
        21.01.2016 12:51

        Мне RawTherapee нравится. Правда фотки больше научного характера. Камера микроскопа, макрофотографии образцов со штатива…


        1. kAIST
          21.01.2016 16:16

          Я не буду говорить про цвет, профили камер и объективов, это все субъективно.
          Когда ты целыми днями работаешь с программой, любой косяк интерфейса или тормоза очень и очень мешают.
          Пару фотографий обработать можно, но вот когда их сотни и тысячи (


          1. Meklon
            21.01.2016 20:21

            Lightroom удобнее, согласен. Но у меня большая часть работы в Linux идёт.


    1. aik
      21.01.2016 11:51
      +1

      Это всё же не работа фотографа получилась, а работа программиста.
      О пригодности линукса для фотографа оно не говорит.


      1. d7s2di
        21.01.2016 13:45
        +1

        О пригодности линукса для фотографа говорит использование линукса фотографом.


        1. aik
          21.01.2016 13:56

          То есть если фотограф на линукс-машине только лазит по интернету — это тоже считается «использованием линукса фотографом»?


          1. d7s2di
            21.01.2016 13:59

            Нет. Это значит, если фотограф использует линукс для работы с фотографией.


            1. aik
              21.01.2016 14:35
              +2

              В описываемом случае — не фотограф, а программист.


  1. AlexeiZhuravlev
    21.01.2016 11:07
    +1

    Вы молодец! Ограничения всегда порождают продуманные и интересные решения.


  1. nikitasius
    21.01.2016 18:55

    Например, на очереди статья, как сделать вот такую милую и функциональную фотобудку

    Можно карманный принтер к фотоаппарату синей изолентой примотать, дешево и сердито!


  1. rhamdeew
    22.01.2016 15:27

    Шикарный пост!

    У вас так понимаю Canon с карточками формата Compact Flash? Это к телефону картридер еще нужно подключать?


  1. FSerg
    26.01.2016 10:56
    +1

    Голосую за статью про фотобудку!


  1. Garrett
    26.01.2016 19:59

    exiftool можно заменить на pyexiv2, больше возможностей и код проще


    1. kAIST
      26.01.2016 20:02

      Спасибо, посмотрю на него еще раз — когда то у меня с ним не срослось, не помню почему.
      Pillow кстати тоже может читать exif, но почему то не все теги и не всегда )

      from PIL import Image,ExifTags
      img=Image.open(PATH_TO_IMAGE)
      exif=dict((ExifTags.TAGS[k], v) for k, v in img._getexif().items() if k in ExifTags.TAGS)
      


      1. Garrett
        26.01.2016 20:07

        Да у меня на c++ тоже с exiv2 не срослось, но там видимо отсутствие опыта с самим c++, а как на python попробовал, завелось и заработало на ура сразу же


  1. rrrav
    26.01.2016 23:01

    Да, отличное решение с Linux Deploy! Сразу возникают мысли, как еще можно это использовать. Ведь в кармане у каждого лежит приличный компьютер да еще всегда подключенный к интернет. Можно и веб сервер с интернет магазином на нем развернуть. Хостинг открыть.
    Даже биткоины можно потихоньку майнить :)


    1. kAIST
      26.01.2016 23:55

      Аха, а через час-два бежать искать розетку )
      А вот использовать старенькие смартфоны или планшеты, которые валяются дома — почему нет.