Если вы системный администратор и занимаетесь обслуживанием пользователей, не только в плане исполнения пожеланий по работе программных комплексов, но закупаете, устанавливаете и заменяете компоненты рабочих мест (мониторы, мышки, клавиатуры, системные блоки), то у вас, как и у меня, наверняка скопилось довольно большое количество сломанных клавиатур, где что-то уже не нажимается или стерты буквы. Плюс ко всему, клавиатура это как предмет личной гигиены, как зубная щетка, она хранит историю своего прошлого хозяина, и эта история новому пользователю будет довольно неприятна. Это и крошки под кнопками, частички кожи, грязи, волосы, наконец. Я встречал пользователей, которые работали за клавиатурами покрытыми черным слоем грязи, причем это их совершенно не беспокоило. А мне хотелось пойти и вымыть руки, поработав пару минут за этими рабочими местами.
Таких б/у клавиатур скопилось просто десятки штук, благо в подвале на складе есть место, и они просто лежали в коробке ожидая своей участи.

Мне уже очень давно хотелось их применить в каком-нибудь творческом проекте.
Можно конечно провести соревнование, кто дальше бросит клавиатуру, как обычно устраивают на днях системного администратора, но это слишком банально.
В Интернет не раз видел, как из кнопок клавиатур пытаются создавать некие арт-объекты или картины. Даже здесь на Хабре были такие статьи, как например:
Но хотелось чего-то более масштабного, как например вот такие работы:

На мой вкус, выглядит потрясающе.
Понимаю, что возможности мои более ограничены, чем у данного автора, но попробовать то хочется!
И вот так сложились обстоятельства, что у меня в руках оказался кусок старого оргалита размером 100x73 сантиметра, бывший когда-то задней стенкой еще советского шкафа. Пришла пора превратить его в «произведение искусства».
Стандартный размер клавиш примерно 1.8x1.8 сантиметра. Это где-то 55x40 клавиш на мой лист. Но учитывая разбег при размещении и плавающий размер самих кнопок, пусть будет размер места для размещения 2х2 сантиметра, а значит, на лист влезет 50 в высоту и 36 в ширину. Это 1800 клавиш. В среднем на клавиатуре около 100 клавиш, но подходящих к моей задумке меньше. Получается нужно «раздербанить» минимум 20 клавиатур, а лучше побольше, поэтому в расход пошло порядка 25 клав.
Клавиатуры, скопившиеся на складе, оказались трех основных цветов: это черные, белые и пожелтевшие от времени белые, т.е. просто желтые. Чисто белых оказалось меньшинство. Можно конечно «заморочиться» и восстановить цвет пластика - перекись водорода и ультрафиолетовая лампа в помощь… но, по-моему, это уже перебор.
Сразу встал вопрос, а как выдернуть столько клавиш? Пробовал разные способы, но самым рабочим оказался старый и сломанный «пробойник для витой пары», у него есть замечательный крючок и с его помощью дело пошло. Работы естественно велись в перчатках, чтобы не сточить руки и просто из санитарных соображений. Смотрите сами на фотографиях.


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

В домашних условиях все это «богатство» было хорошо промыто с чистящими средствами, и можно приступать к следующему этапу.
Здесь возникла другая проблемка. Клавиши к листу оргалита я предполагал крепить с помощью клеевого пистолета. Значит, нужна площадка, куда можно нанести клей. Но у разных клавиатур оказались настолько разные посадочные места, что пришлось вооружиться кусачками и немного подровнять некоторые кнопки, чтобы они плотнее прилегали к листу. На этом этапе очень сильно захотелось все бросить, но пересилил себя и продолжил.
Несколько подкосил планы неожиданный больничный. Но в итоге, что айтишнику делать на больничном, когда идешь на поправку?
Итак – клавиши отмыты, подрублены, отсортированы по цветам. Осталось дело за малым, а что собственно изобразить? И как сделать это изображение?
Когда-то, уже довольно давно, на Хабре я встретил вот эту статью:
Краткая суть, это как быстро и просто сделать мозаичное изображение из набора фотографий. На основе этой статьи я сделал свой пример, упростив и улучшив исходный алгоритм, который потом показывал школьникам на занятиях по языку Python.
Принцип в данном случае следующий: у нас есть некий большой набор изображений, для каждого изображения мы вычисляем усредненный цвет и запоминаем его вместе с именем файла изображения. По сравнению с оригинальным кодом из статьи, я немного усложнил подсчет усредненного цвета, разделив исходное изображение на четыре части просто поделив его пополам по высоте и ширине. И для каждой из частей хранится свой средний цвет этого кусочка. Т.е. на один файл – четыре компонента.
Для обработки изображений используется библиотека OpenCV. Очень полезная штука.
Полученный результат сохраняется для дальнейших обработок. Поскольку эта процедура разовая, то все эти действия вынесены в отдельный файл:
import os import cv2 import pickle PATH_TO_PROJECT = r'H:\Project\Keys\Mozaika' items = {} # Результирующий список для сохранения в файл. mypath = os.path.join(PATH_TO_PROJECT, 'image') for i, file in enumerate(os.listdir(mypath)): file1 = os.path.join(mypath, file) img = cv2.imread(cv2.samples.findFile(file1)) size = img.shape sy = size[0] sx = size[1] sx2 = sx//2 sy2 = sy//2 # Каждое изображение делим на четыре части. img00 = img[0:0+sy2, 0:0+sx2] img10 = img[0:0+sy2, sx2:sx2+sx2] img01 = img[sy2:sy2+sy2, 0:0+sx2] img11 = img[sy2:sy2+sy2, sx2:sx2+sx2] allimg = [img00, img10, img01, img11] spisok = list() for im in allimg: # Вычисляем среднее значение цвета для каждой из частей r = round(im[:, :, 0].mean()) g = round(im[:, :, 1].mean()) b = round(im[:, :, 2].mean()) spisok.append((r, g, b,)) items[file1] = spisok with open(os.path.join(PATH_TO_PROJECT, 'data.pickle'), 'wb') as f: pickle.dump(items, f)
Затем в другом файле обрабатываем изображение, которое хотим представить в виде мозаики.
Загружаем наш список средних цветов и названий файлов, сформированный на предыдущем шаге, из файла data.pickle.
Также загружаем исходное изображение, с ним проделываем операцию похожую на действия в предыдущем файле. Делим его на квадраты и каждый квадрат обрабатываем, разделяя его еще на четыре части. Получаем средние значения всех четырех частей и ищем похожие значения для этого квадрата среди ранее обработанных файлов. Найдя похожие значения, просто заменяем в исходном изображении этот квадрат на подобранное изображение.
import os import cv2 import pickle import random def lost_function(spisok, arg): spisok_a = arg[1] summ = 0 for i, im in enumerate(spisok_a): for j, color in enumerate(im): summ += abs(color - spisok[i][j]) return summ vs = 80 # Вертикальный и горизонтальный размер ячеек, на которые делится изображение. hs = 80 PATH_TO_PROJECT = r'H:\Project\Keys\Mozaika' with open(os.path.join(PATH_TO_PROJECT, 'data.pickle'), 'rb') as f: items = pickle.load(f) img = cv2.imread(os.path.join(PATH_TO_PROJECT, 'item_1.jpg')) height, width, d = img.shape img = cv2.resize(img, (width - (width % vs), height - (height % hs))) # Выравниваем изображение, чтобы делилось на равные части. height, width, d = img.shape for x in range(0, width, hs): # Проходим по квадратам на изображении и каждый квадрат обрабатываем как еще четыре квадрата. for y in range(0, height, vs): sect = img[y:y+vs, x:x+hs] sy, sx, sd = sect.shape sx2 = sx // 2 sy2 = sy // 2 img00 = sect[0:0 + sy2, 0:0 + sx2] img10 = sect[0:0 + sy2, sx2:sx2 + sx2] img01 = sect[sy2:sy2 + sy2, 0:0 + sx2] img11 = sect[sy2:sy2 + sy2, sx2:sx2 + sx2] allimg = [img00, img10, img01, img11] spisok = list() for im in allimg: # Находим среднее значение ��вета в части квадрата. r = round(im[:, :, 0].mean()) g = round(im[:, :, 1].mean()) b = round(im[:, :, 2].mean()) spisok.append((r, g, b,)) current = sorted(items.items(), key=lambda argument: lost_function(spisok, argument))[0] # Находим наиболее близкое по среднему цвету изображение. resized = cv2.resize(cv2.imread(current[0]), (vs, hs,)) # Преобразуем изображение к нужному нам размеру ячейки. img[y:y+vs, x:x+hs] = resized # Замещаем ячейку изображением. cv2.imshow('ImageWindow', img) cv2.imwrite(os.path.join(PATH_TO_PROJECT, 'out.jpg'), img) # Сохраняем итоговое изображение. cv2.waitKey(0)
Зачем я делю каждый квадрат изображения еще на четыре части? Для более точного подбора картинки. Посмотрите на примеры: слева изображение, сделанное без разделения на четвертинки, справа с разделением. Разница очевидна:



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



Три изображения с выровненными клавишами, которые уже легко разрезать на одинаковые части. Здесь лень во мне победила и вместо того, чтобы самому написать эту программку, воспользовался готовым сервисом:
В результате я получил 270 файлов с изображениями клавиш, для последующего формирования из них мозаики.
Остался еще один немаловажный вопрос: что изобразить? Картина должна быть приличного содержан��я, чтобы ее можно было повесить в кабинете на работе, она должна быть узнаваема, поскольку разрешение у нее будет 50 на 36 пикселей, а это не очень много.
В итоге выбор пал на «Джоконду» Леонардо да Винчи. Оригинал картины выполнен в довольно темных тонах и превращение ее в мозаику получалось не очень красивым. Привожу пример

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

Пока мучился с поиском картины, перебрал множество вариантов и одним из удачных был Фрай из Футурамы

Но у меня, к сожалению, не было столько белых клавиш.
Итак, продолжаем: разлиновываем наш лист на нужное количество частей и начинаем процесс наклейки.
Сам процесс занял в общей сложности часов 5-6, за два вечера я все сделал. На всё ушло две с небольшим упаковки клеевых палочек, это где-то 30 штук. Сначала я пытался подбирать клавиши именно такие, какие получились на изображении мозаики, но очень быстро понял, что это нереально и уже клеил все подряд, главное чтобы цвет совпадал.
Осталось найти место в рабочем кабинете, чтобы это повесить.
Результат получился несколько хуже, чем я рассчитывал, но лучше чем могло быть :)
Не судите строго, это просто эксперимент заскучавшего айтишника.
Исходный текст и изображения можно найти по ссылке:
