Ловим кошек в Instagram
Технологии машинного обучения с каждым днем находят новые и новые сферы применения. Становится ясно, что следующая эпоха за machine learning и big data. Но, к сожалению, порог вхождения довольно высок для не подготовленного человека. Давайте же немного приоткроем занавес и попробуем сами пощупать machine learning на примере компьютерного зрения своими руками.
Ставим задачу
Найти все фотографии в профиле instagram с изображением котов.
Приступим
Для начала напишем скрипт, который получит все посты определенного аккаунта. Вариантов, как это сделать довольно много, но я остановился на библиотеке Instaloader мне она показалась довольно простой, функциональной с минимальным набором зависимостей. Итак, ставим:
pip3 install instaloader
Далее напишем сам скрипт:
# cat_detector.py
from instaloader import Instaloader, Profile
PROFILE = '<instagram profile here...>'
def main():
loader = Instaloader()
post_iterator = Profile.from_username(loader.context, PROFILE).get_posts()
for i, post in enumerate(post_iterator, 1):
print(post.caption)
print(post.url)
print('-' * 10)
if __name__ == '__main__':
main()
Просто, не правда ли?
Окей, мы получили картинки из постов профиля, дело осталось за малым - выбрать из них те, на которых изображены котики >^_^<. Для этого мы будем использовать библиотеку ImageAI, которая очень проста и супер функциональна, сейчас убедимся:
# ставим imageai и зависимости
pip install imageai tensorflow opencv-python keras
Также нам необходимо будет скачать файл https://github.com/OlafenwaMoses/ImageAI/releases/download/1.0/yolo.h5 и положить его рядом с нашим скриптом, который представляет из себя сохраненную модель нейронной сети, которая уже обучена распознавать тысячи различных объектов.
Теперь обновим наш скрипт:
# cat_detector.py
import os
import io
from PIL import Image
from instaloader import Instaloader, Profile
from imageai.Detection import ObjectDetection
PROFILE = '<instagram profile here...>'
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
def has_cat(detections):
for detection in detections:
if detection['name'] == 'cat':
return True
return False
def main():
detector = ObjectDetection()
detector.setModelTypeAsYOLOv3()
detector.setModelPath(os.path.join(BASE_DIR, "yolo.h5"))
detector.loadModel()
loader = Instaloader()
post_iterator = Profile.from_username(loader.context, PROFILE).get_posts()
for i, post in enumerate(post_iterator, 1):
raw_image = loader.context.get_raw(post.url)
image_array, detections = detector.detectObjectsFromImage(
input_image=io.BytesIO(raw_image.raw.read()),
input_type='stream',
output_type='array',
minimum_percentage_probability=30)
if has_cat(detections):
im = Image.fromarray(image_array)
im.save(os.path.join(BASE_DIR, 'output', '{}.jpg'.format(i)))
print("Cat detected! See image: output/{filename}.jpg\n\n"
"{caption}\n"
"{url}\n\n".format(
filename=i,
caption=post.caption,
url=post.url
))
print('*' * 10)
if __name__ == '__main__':
main()
Также создадим папку output, в которую наш скрипт бережно сложит всех найденых котов.
Пробуем запустить:
python3 cat_detector.py
И все коты найдены.
Что здесь происходит?
Давайте пройдемся по нашему скрипту и разберем основные моменты.
PROFILE = '<instagram profile here...>'
Здесь мы указываем профиль посты которого мы будем анализировать.
def has_cat(detections):
for detection in detections:
if detection['name'] == 'cat':
return True
return False
Простая функция которая вернет True, если среди всех найденых объектов есть объект с именем cat.
detector = ObjectDetection()
detector.setModelTypeAsYOLOv3()
detector.setModelPath(os.path.join(BASE_DIR, "yolo.h5"))
detector.loadModel()
Создаем и инициализируем наш детектор, в качестве модели указываем скачанный нами раннее файл yolo.h5.
loader = Instaloader()
post_iterator = Profile.from_username(loader.context, PROFILE).get_posts()
Создаем post_iterator, который позволит нам получать один за одним посты пользователя.
raw_image = loader.context.get_raw(post.url)
Скачиваем изображение поста по url.
image_array, detections = detector.detectObjectsFromImage(
input_image=io.BytesIO(raw_image.raw.read()),
input_type='stream',
output_type='array',
minimum_percentage_probability=30)
Здесь происходит основная магия - мы передаем скачанную картинку нашему детектору. Остановимся подробнее на параметрах:
- input_image - входное изображение, может принимать имя файла, массив и поток;
- input_type - тип входного изображения, по умолчанию `file`. Может так же принимать значения `array` или `stream`;
- output_type - формат выходного изображения, может быть или `file`, или `array`;
- minimum_percentage_probability - минимальный процент “уверенности” нашего детектора в правильности распознанного объекта.
if has_cat(detections):
im = Image.fromarray(image_array)
im.save(os.path.join(BASE_DIR, 'output', '{}.jpg'.format(i)))
Если среди найденых объектов есть представители семейства кошачих, то нужно сохранить изображение в папку output.
Заключение
Надеюсь, вам понравилась задача и простота используемых инструментов. Если вы хотите разобраться подробнее, можете ознакомится с документацией на страницах проектов:
Instaloader https://github.com/instaloader/instaloader