<< | #253 ; La strukturo de foto en Python -programo |
>> |
Certe la granda programaro OpenCV estas tre bona kaj forta laborilo por komputila vidkapablo, sed ni prefere unue pritraktu la plej bazajn kaj simplajn ecojn de fotoj, tiel kiel la komputila Python -programo ilin vidas. Kiel ekzemplo ni havas la apudan malgrandan foton. Ĝi prezentas ian tradician muzikan instrumenton, harmonikon, kion mi vidis en la malnova stacidomo de Kurikka, Suda Ostrobotnio. Oni eĉ produktis la muzikilon en komunumo Kurikka. La firmao de sinjoro S.ELOMAA kredeble konstruis la harmonikon kaj certe multaj aliaj.
La iom malgranda kolora foto estas 300 punktoj larĝa kaj 200 punktoj alta. Ni povas iom angle diri ke estas 300 * 200 pixel en la foto. Do la foto enhavas sume 60000 koloraj punktoj, ĉu iom multe por tia malgranda foto? Ofte fotoj de fotiloj estas ĝene kaj ĉagrene grandaj se oni ilin aparte ne malgrandigas. Certe ankaŭ ĉi tiu foto estis origine multe pli granda.
En la foto estas vertikale 200 vicoj kaj horizontale 300 kolonoj por koloraj punktoj. Ĉiu el la 200 vicoj de foto enhavas horizontale 300 punktoj en kolonoj kaj ĉiu el la 300 kolonoj havas vertikale 200 punktoj en vicoj.
La grando de datumo por tiu foto estas 43909 bytes en la iom pakita .JPG datumo, do iom granda por tia malgranda foto. Estas relative multe da informo en la foto kaj tial ne eblas paki ĝin tre bone, sen perdi tro multe da informo. Apudaj punktoj de foto ofte estas iom similaj kaj tial eblas densigi kaj paki la informon sen granda malutilo.
En la memoro de komputilo ĝi tamen bezonas kiel nombroj pli multe da memoro en Python-programo ; ĉiu kolora punkto bezonas 3 bytes ĉar oni uzas tri nombroj je valuoj 0 ... 255 por prezenti la 3 koloroj, R(ed), G(reen), B(lue) de unu punkto. En la memoro la foto do bezonas en nombroj sume 300 * 200 * 3 = 180000 nombroj je valuoj en intervalo 0 ... 255, do sume 180000 bytes, pli ol kvaroble da memoro kompare al la pakita .JPG datumo.
Ni iom pritraktu kiel oni povas legi la foton per Python-programo kaj esplori ĝin en Raspberry Pi. Por tio ni tamen nepre bezonas ankaŭ la plian sciencan parton NumPy
por Python por pli facile vidi la nombran enhavon de foto.
from PIL import Image from numpy import * # por uzi 'array' im = Image.open('/home/pi/Kuvat/i4016.jpg') print (im.size) # La grando de foto en punktoj: (300, 200) # Nun ni tamen malfermas la saman foton iom alie, kiel tabulo de nombroj: im2 = array(Image.open('/home/pi/Kuvat/i4016.jpg')) print (size(im2)) # La grando de foto en nombroj: 180000 print (size(im2[0])) # 900 = 3 * 300 print (size(im2[0][0])) # 3 print (size(im2[0][0][0])) # 1
Kiam estas la valuo por la grando (size) de im2[0] = 900
, tio signifas ke ekzistas 900 da nombroj en tabulo nomita im2
por la unua indekso [0] de tabulo. Tamen la tabulo estas kvadrata en formo, kaj tial ekzistas 900 da nombroj ankaŭ por ĉiuj tiuj 200 indeksoj en la unua dimensio de tabulo, do sume 200 * 900 = 180000 nombroj en la tabulo, la sama kvanto kiel antaŭe.
Ni vidas ke estas 3 dimensioj por la tabulo de kolora foto. La unua dimensio (en ĉi tiu kazo la 200 nombroj 0 ... 199) estas la nombro de vico en la foto, nombrita el supro de foto malsupren. La dua dimensio (en ĉi tiu kazo la 300 nombroj 0 ... 299) estas la nombro de kolono en la foto, nombrita el maldekstra rando de foto dekstren.
La tria dimensio (la 3 nombroj 0 ... 2) en la kolora foto estas por la koloroj (la 256 diversaj valuoj 0 ... 255) de punkto. La unua nombro [0] estas por koloro ruĝa (R), la dua nombro [1] estas por la koloro verda (G) kaj la tria nombro [2] estas por koloro blua (B).
Eble la apuda desegnaĵo maldekstre iom klarigas la aferon. Ni havas en la foto kvazaŭ 3 tavoloj da nombroj, unu tavolo por ĉiu koloro, RGB, valuoj por la kvanto de koloroj ruĝa, verda kaj blua.
Nia ekzempla foto havas 200 vicoj da koloraj punktoj, la nombroj de vicoj en intervalo 0 ... 199. Nia kara foto havas ankaŭ 300 kolonoj da koloraj punktoj, la nombro de kolono en intervalo 0 ... 299.
Ĉiuj punktoj de foto havas valuojn por la tri koloroj RGB. La valuoj estas en intervalo 0 ... 255, do 256 diversaj alternativoj. Ni ja scias ke egalas 28 = 256 kaj ekzistas 8 bits en unu byte. Do 255 estas la plej granda nombro kion oni povas esprimi per 8 bits (nombroj por bazo 2) kiuj povas havi nur la valuojn 0 aŭ 1.
Nome per 8 bits estas la 2-baza nombro 111111112 la plej granda kaj la valuo estas en nia norma bone konata nombra sistemo de bazo 10 (dek) la sama kiel la sekvanta sumo: 1*27 + 1*26 + 1*25 + 1*24 + 1*23 + 1*22 + 1*21 + 1*20 = 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 25510, do egala al 1*28 - 1 = 256 - 1 = 255.
Nu, fakte nacilingvismoj kiel "bit" kaj "byte" tute ne estas bone en honesta Esperanta teksto. Mi devas nun forte klopodi por apartiĝi el tiaj anglismoj kaj por pli bone lerni la internacian lingvon Esperanto! La Vikipedio nin helpu. Nia kara lingvo Esperanto ja tute ne havas la literon W kaj tial la ĝenerale konata "Wikipedia" estas en nia lingvo Vikipedio.
Simplaj aferoj estas iam surprize kompleksaj. Miaj proksimume 50 jaroj aĝaj libraj Esperanto-vortaretoj tute ne havas modernaj teknikaj komputilaj vortoj. Jen iom da pli bona nova Esperanto en Vikipedio:
En daŭrigo mi sincere klopodos por uzi la korektajn Esperantajn vortojn en teknika Esperanta teksto.
Cetere, nigra kaj blanka foto (kiu enhavas nur diversaj tonoj de griza) ne havus la trian dimension. Ni povus transformi la saman koloran foton al nigra kaj blanka por vidi tion:
bw = array(Image.open('/home/pi/Kuvat/i4016.jpg').convert('L')) print (bw.size) # La sama foto kiel nigra kaj blanka: 60000 nombroj print (size(bw[0])) # 300 ; do 300 kolonoj kaj 200 vicoj print (size(bw[0][0])) # 1 ; nur unu nombro anstataŭ 3 por kolora foto
En nia Python -programo ni povas esplori la kolorojn de unu punkto en la maldekstra supra angulo [0][0] de origina kolora foto:
print (im2[0][0]) # La RGB-koloroj de punkto estas: [166 170 169] print (im2[0][0][0], im2[0][0][1], im2[0][0][2]) # La sama informo kiel supre
Do la punkto havas samtempe 166/255 da ruĝa koloro, 170/255 da verda koloro kaj 169/255 da blua koloro. Tial estas relative hela punkto. Se ĉiuj 3 nombroj por la punkto estus 255, estus la punkto tute blanka en koloro. Se ĉiuj 3 nombroj por la punkto estus 0 (nulo), estus la punkto tute nigra.
Ni povas ekzemple desegni per programo por la kolora foto ruĝan [0] linion por la sesa vico [5] kaj verdan [1] linion por la centunua kolono [100] tiel ke ni simple aliigas la nombrojn en la tabulo:
for i in range(300): im2[5][i][0] = 255 for i in range(200): im2[i][100][1] = 255
La plano estas por uzi OpenCV por la 3D-fotilo, sed ni povas labori kun la fotoj ankaŭ sen la bona programaro OpenCV. En la daŭrigo ni espereble vidos ekzemploj.
Kaj jen ni havas novan exemplan foton, malnova vapora lokomotivo en somera pejzaĝo de malnova stacio. Per la sekvanta Python -programo ni povas produkti iom alian koloran foton el tio origina foto.
from PIL import Image from numpy import * import matplotlib.pyplot as plt from pylab import * from scipy.ndimage import filters im2 = array(Image.open('/home/pi/Kuvat/i3966.jpg')) im2[:,100,:] = [255,0,0] # Ruĝa linio por kolono 100 im2[150,:,:] = [0,0,255] # Blua linio por vico 150 im2 = 255 - im2 # Aliaj koloroj ... im3 = zeros(im2.shape) for i in range(3): im3[:,:,i] = filters.gaussian_filter(im2[:,:,i], 1) im3 = uint8(im3) figure() title("Kolora foto") plt.imshow(im3) plt.show()
Kion ni faris por la foto? Unue ni desegnis du novaj linioj por la foto.
Sekve ni aliigis ĉiujn kolorojn en la foto tre simple per unu simpla komando : im2 = 255 - im2
. Koloroj en la nova foto estas jam tute aliaj. Ekzemple la nova ruĝa linio en kolono 100 fariĝis blua. La nova blua linio en vico 150 fariĝis flava.
Sekve ni uzis Gaussian -filtrilon por iom "moligi" la foton tiel ke la randoj aperas pli molaj.
Certe la koloroj estas tute falsaj, se oni ankoraŭ facile vidas ke estas lokomotivo en la bildo.
Pli bone eble estas por prilabori "nigraj kaj blankaj" fotoj (ĉu eble pli bone nomitaj "grizaj" fotoj?).
Sekvanta vario de principe sama lokomotiva foto estas prilaborita per Sobel -filtrilo. Ĝi montras la randojn en la "nigra kaj blanka" foto.
Ofte ni nome volas scii kie estas la randoj en la foto. Ni esperas ke rando en la foto estas ankaŭ vera rando en la fotita objekto, sed tio ne pravas ĉiam. Koloro en la objekto povas esti alia, sed estas tamen ankoraŭ la sama objekto. Lumigado povas esti alia. Eble estas nur ombro kio falas sur la objekto?
Multe da problemoj en komputila vidkapablo. Ĉiuokaze randoj estas gravaj kiam ni volus konturi la objekton el sia fono.
Jen la programo. La komenco estas la sama kiel antaŭe.
bw = array(Image.open('/home/pi/Kuvat/i3966.jpg').convert('L')) # Nigra kaj blanka vario de foto # Sobel -filtrilo por trovi la randojn en la foto imx = zeros(bw.shape) imy = zeros(bw.shape) magnitudo = sqrt(imx**2 + imy**2) bw = filters.sobel(bw, 0, magnitudo) figure() plt.gray() title("Sobel-filtrilo") plt.imshow(bw) plt.show()
Teorio estas peza se oni devas scii multe da detaloj, sed feliĉe ekzistas multe da pretaj programoj kiuj (espereble) estas facilaj por uzi. Tiom multe ni progresis sen la bona OpenCV, sed certe ĝi estas nia vera celo.
La fenomeno de Moiré estas ofte grava por fotoj: Muaro. Tial indas forigi tro grandaj frekvencoj en foto se oni volas ĝin malgrandigi. Mi iom malgrandigis la origine .PNG -fotojn el Matplotlib.
Kaj certe fine ..........
NI VENKOS!
La Ambasadoro en Pori de sendependa nacio Mueleja Insulo |