Skirtingai nei Polaroidas, šis fotoaparatas naudoja čekių spausdintuvą - tokį pat, kuris tau parduotuvėj atspausdina ką ir už kiek pirkai. Nuotraukų kokybė nėra tokia pati kaip Polaroido, bet šios, sakykim, turi savotiško žavesio.
Vargšo žmogaus Polaroidas nereiškia, kad šitas aparatas yra itin pigus, gal labiau papigiai sukurtas, nes pačios dalys man kainavo daugiau nei pigiausias Polaroidas.
Nors dalys kainavo ir daugiau, bet galiausiai išeis sutaupyt ant pačių nuotraukų - Polaroido nuotrauka kainuoja maždaug 1 eurą, o mano fotoaparato nuotrauka - mažiau nei 1 centą (50 metrų čekių popieriaus rulonas kainuoja porą eurų).
Kamera
Šnekant apie kamerą, turiu paminėti, jog ji yra prijungta prie mažo kompiuterio, kuris apdoroja nuotrauką ir nusiunčia ją spausdintuvui.
Kompiuteris - Raspberry Pi Zero
Tai yra tikras kompiuteris, toks pat kaip tavo laptopas ar stacionari dėžė, gal ne toks galingas (nebent nekeitei kompo jau 25 metus), bet vis tiek kompiuteris - gali prijungti ekraną, klaviatūrą, pelę, taip pat yra bluetooth ir wifi. Be viso to, prie jo galima prilituot lempų, mygtukų, sensorių ir užprogramuot juos, kad vykdytų tavo technologines užgaidas.
Taip pat yra jam skirtas kameros modulis, lengvai naudojamas ir neužima daug vietos.
Raspberry Pi kamera su laidu
Elektra
Kompiuterį gali pajungti į rozetę, tačiau toli nuo jos nepafotografuosi, nebent turi labai ilgą elektros laidą. Labai ilgą.
Arba gali nusipirkti pakraunamą batareiką, įtampos keitiklį, krovimo valdiklį ir pasigaminti pakrovėją pats.
Savadarbio pakrovėjo dalys
Kad nereikėtų nešiotis elektros laido ritės ar montuoti batareikų pakrovėjo pačiam, gali įsigyti power banką, ką aš ir padariau. Kažkodėl tai kainavo mažiau nei atskiros dalys.
Power bankas, taip pat rodo baterijos įkrovos lygį
Susirask įrankių, apsauginius akinius ir būk budrus, kada besi kažką aštraus į power banką - jei pradursi pačią bateriją, bus kaip žvakutė ant torto, kurios neįmanoma užpūst, tik žymiai blogiau. Daugumą degančių dalykų gali užgesinti su kibiru vandens, tačiau šitoj situacijoj reikės kibiro smėlio, kad, tiesiogine prasme, uždusintum ugnį.
Power bankas pusiau išrinktas, liepsnų nėra
Išrinktas power bankas, vis dar be liepsnų
Spausdintuvas
Šis spausdintuvas nėra ypatingas - jis tiesiog mažas, reikalauja specifinio popieriaus ir vietoj rašalo spausdina kaitindamas popierių. Gerai, gal kažkiek ir ypatingas... bet kokiu atveju - štai keli spausdintuvai, kuriuos turiu.
Pamiršau padaryti nuotrauką prieš pradėdamas lukštenti vieną iš spausdintuvų
Norint prisijungti prie spausdintuvo, galima naudoti laidą arba bluetooth. Teoriškai gali padaryti nuotrauką su telefonu ir ją nusiųsti spausdintuvui per bluetooth, bet praktiškai tai neturėsi progos pabandyt išrinkti power banką ir padegt namus - pasirinkimas aiškus.
Po teisybei, nelabai daugiau ką turiu pridėt - pirkau juos iš Kinijos, vienas kainavo 20 eurų, kitas 60, turėjo būti vienodi, bet žinoma taip nebuvo. Jei nori įsigyti pats – ieškok modelio "PT-310", ir eee, sėkmės.
Dėžė
Susiradau liniuotę, kad galėčiau išmatuot šitą kreivos formos spausdintuvą.
Galėjo padaryti kvadratinį, bet neee
Pasinaudojau FreeCAD, kad sukurčiau dėžės modelį, ir atspausdinau 3D spausdintuvu.
Išėjo kelios dalys - į vieną įdėsiu spausdintuvą, į kitą bateriją su kompiuteriu, jos turėtų susidėt kaip sumuštinis. Taip pat mygtukų laikiklis ir kosmetinės gražuomenės.
Pašlifavęs sudėjau viską į vietas, kad pamatyt, kaip tai atrodo.
Tuomet užpurškiau glaisto, kad užkišt tarpus.
Ir galiausiai - dažai. Minty geltona su juoda atrodė gerai.
Ė, ir atrodo gerai
Susirinkimas
Beliko užpilt biški klijų, įsukt kelis varžtelius, šiek tiek paprogramuoti ir susirinkimas bus įvykęs. O toliau - susirinkimo dalyviai.
LED lemputės, kas be ko
Įdėjau kelias lemputes, kad būtų aišku, kas vyksta. Mėlyna - elektra yra, žalia - aparatas pasiruošęs naudojimui, raudona - vyksta naudojimas (kitaip sakant, daroma nuotrauka, kai paspaudi mygtuką).
Raspberry Pi neturi įjungimo/išjungimo mygtuko. Gali išjungti ištraukęs maitinimo kabelį (nepatartina), arba įmontuot ir užprogramuot mygtuką, kuris pasakytų kompiuteriui, kad laikas pailsėti (patartina). Deja, šis mygtukas gali tik išjungti kompiuterį, bet neįjungti. Įjungimui prie maitinimo laido įtaisiau jungiklį, kurį reikia paspaust po išjungimo - jis tiesiog atjungia elektrą. Norint vėl įjungti, paspaudi jungiklį ir elektros srovė pradeda tekėti - tas pats, ką darai norėdamas uždegti šviesą tualete.
Išjungimo mygtukas ir elektros jungiklis
Fotoaparato priekyje dar yra mygtukas padaryti nuotraukai - jis matosi viršuj dešinėj, kartu su kompiuteriu, baterija (prispausta juoda plokštele), įjungimo/išjungimo mygtukais ir lemputėmis.
Fotoaparato priekio vidus
Gaila, kad dėl laidų kiekio tai atrodo kaip makaronų lėkštė. Geriausia, ką galėjau padaryti, tai naudoti skirtingų spalvų laidus, kad žinočiau, ką prie ko jungti.
Kitoje fotoaparato pusėje įtaisiau spausdintuvą, pragręžęs jame kelias skyles, kad galėčiau pritvirtint su varžtais.
Ten pat yra power banko modulis (išluptas iš power banko, turi ekraną ir lizdą pakrovimui) ir dar vienas mygtukas, kuris atspausdina paskutinę nuotrauką, jei norėčiau dviejų kopijų (vieną tau ir vieną man).
Zjbs, dar daugiau laidų. Du - mygtukui, keturi - elektrai ir dar pora - dalykui, kurį radau power banke - termometrui. Jei baterija perkaista, termometras tai pajaučia ir atjungia elektros srovę, kad neužsidegtų namai - ką labai vertinu, įtariu, vertina ir mano kaimynai.
Padaryk Nuotrauką
Per daug nesigilinant į detales, programavimui naudojau Python kalbą vien dėl to, kad jau yra daug kitų žmonių parašytų dalykų, kurie man lengvai leis apdoroti nuotraukas, naudoti patį Raspberry Pi ir jo kamerą. Jei smalsu - visą programos kodą gali rast žemiau.
from PIL import Image, ImageEnhance from escpos.printer import Usb from picamera2 import Picamera2 import RPi.GPIO as GPIO import cv2 import numpy as np import os import signal import threading import time import io shots_dir = './shots' last_image = None os.makedirs(shots_dir, exist_ok=True) camera_busy = False reprint_busy = False PRINTER_VENDOR_ID = 0x28e9 PRINTER_PRODUCT_ID = 0x0289 GPIO.cleanup() POWER_LED_PIN = 23 CAMERA_LED_PIN = 4 POWER_BUTTON_PIN = 22 CAMERA_BUTTON_PIN = 27 REPRINT_BUTTON_PIN = 26 GPIO.setmode(GPIO.BCM) GPIO.setup(POWER_LED_PIN, GPIO.OUT) GPIO.setup(CAMERA_LED_PIN, GPIO.OUT) GPIO.setup(POWER_BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(CAMERA_BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(REPRINT_BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) picam = Picamera2() camera_config = picam.create_still_configuration({"size": (2000, 2000)}) picam.align_configuration(camera_config) picam.configure(camera_config) picam.set_controls({"FrameRate": 1}) picam.start() GPIO.output(CAMERA_LED_PIN, GPIO.LOW) GPIO.output(POWER_LED_PIN, GPIO.HIGH) def get_image_brightness(image): grayscale = image.convert('L') histogram = grayscale.histogram() pixels = sum(histogram) brightness = sum(i * count for i, count in enumerate(histogram)) / pixels return brightness def histogram_equalization(image): img_gray = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2GRAY) equalize_hist = cv2.equalizeHist(img_gray) equalized_image = Image.fromarray(equalize_hist) return equalized_image def gamma_correction(image, gamma=0.7): img_array = np.array(image) / 255.0 corrected_array = np.power(img_array, gamma) corrected_image = Image.fromarray((corrected_array * 255).astype('uint8')) return corrected_image def apply_clahe(image): img_gray = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2GRAY) clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) clahe_applied = clahe.apply(img_gray) equalized_image = Image.fromarray(clahe_applied) return equalized_image def contrast_stretch(image, low=50, high=200): img_array = np.array(image) min_val = np.min(img_array) max_val = np.max(img_array) stretched = (img_array - min_val) * ((high - low) / (max_val - min_val)) + low stretched = np.clip(stretched, 0, 255) stretched_image = Image.fromarray(stretched.astype('uint8')) return stretched_image def camera_button_callback(channel): global last_image, camera_busy if camera_busy: return camera_busy = True def job(): global last_image, camera_busy try: GPIO.output(CAMERA_LED_PIN, GPIO.HIGH) timestamp = int(time.time()) filename = f"shots/image_{timestamp}.jpg" picam.capture_file(filename) GPIO.output(CAMERA_LED_PIN, GPIO.LOW) image = Image.open(filename) image = image.resize((576, int(image.height * 576 / image.width))) brightness = get_image_brightness(image) if brightness < 60: image = histogram_equalization(image) elif brightness < 90: image = gamma_correction(image) elif brightness < 110: image = apply_clahe(image) elif brightness < 130: image = gamma_correction(image) else: image = contrast_stretch(image) converted_filename = f"shots/image_{timestamp}_converted.jpg" image.save(converted_filename) last_image = io.BytesIO() image.save(last_image, format='JPEG') last_image.seek(0) printer = Usb(PRINTER_VENDOR_ID, PRINTER_PRODUCT_ID) printer.image(converted_filename) printer.textln() printer.textln() printer.close() os.remove(converted_filename) except Exception as e: print(f"Error during capture/print: {e}") finally: camera_busy = False threading.Thread(target=job, daemon=True).start() def power_button_callback(channel): os.system('shutdown now') def reprint_button_callback(channel): global last_image, reprint_busy if reprint_busy: return reprint_busy = True def job(): global last_image, reprint_busy try: if last_image is None: return GPIO.output(CAMERA_LED_PIN, GPIO.HIGH) printer = Usb(PRINTER_VENDOR_ID, PRINTER_PRODUCT_ID) printer.image(Image.open(last_image)) printer.textln() printer.textln() printer.close() GPIO.output(CAMERA_LED_PIN, GPIO.LOW) finally: reprint_busy = False threading.Thread(target=job, daemon=True).start() def cleanup(): GPIO.output(CAMERA_LED_PIN, GPIO.HIGH) GPIO.cleanup() picam.close() GPIO.add_event_detect(CAMERA_BUTTON_PIN, GPIO.FALLING, callback=camera_button_callback, bouncetime=200) GPIO.add_event_detect(POWER_BUTTON_PIN, GPIO.FALLING, callback=power_button_callback, bouncetime=200) GPIO.add_event_detect(REPRINT_BUTTON_PIN, GPIO.FALLING, callback=reprint_button_callback, bouncetime=200) stop_event = threading.Event() def worker(): while not stop_event.is_set(): time.sleep(1) def handle_signal(signal_num, frame): cleanup() stop_event.set() signal.signal(signal.SIGTERM, handle_signal) signal.signal(signal.SIGINT, handle_signal) thread = threading.Thread(target=worker, daemon=True) thread.start() stop_event.wait()
Raspberry Pi kamera nėra bloga, bet ir ne ypatingai gera - kartais nuotrauka būna per tamsi, kartais per šviesi, todėl kode gali rasti daug funkcijų, kurios apdoroja nuotrauką, priklausomai nuo to, kiek ji yra šviesi.
Skirtingai apdorota ta pati nuotrauka. Labas, Kenny!
Per daugelį bandymų išsiaiškinau, kada su kuria funkcija apdorot nuotrauką, ir aparatas gatavas.
Žemiau gali pažiūrėt video, kaip šitas daiktas veikia.
Jei ir tu nori magiškos foto dėžės - susisiek su manim, kontaktus rasi puslapio apačioj.