Millä koodilla voi verrata kahta kuvaa ja kertoa kuvien keskimääräinen eroavaisuus tulostettavassa ja ymmäretttävässä muodossa? (esim. Kuvassa on 10% ero)
Mitä tarkoittaa kuvien ero? Jos on kaksi shakkiruudukkoa, joiden väritys on vastakkainen (toinen alkaa valkoisesta ja toinen mustasta ruudusta), paljonko eroa kuvilla on? Ihmisen mielestä ero on kohtalaisen pieni, mutta kaikkien tällaisten tilanteiden tunnistaminen tietokoneella on hyvin hankalaa.
Jos sinulle riittää kuvista vastaavien pikselien vertailu (eli äsken mainitussa tapauksessa ero on 100 %), voit vain lukea kuvat, muuttaa ne samaan muotoon (RGB) ja silmukassa laskea pikselien värien komponenttien erotusten itseisarvojen summan jaettuna kaikkien pikseleiden komponenttien vaihteluvälien summalla. Koodista tulee suunnilleen tällainen:
BufferedImage i1, i2; i1 = ImageIO.read(new File("kuva1.jpg")); i2 = ImageIO.read(new File("kuva2.jpg")); int w = Math.min(i1.getWidth(), i2.getWidth()); int h = Math.min(i1.getHeight(), i2.getHeight()); // TODO: Huomioi kuvien kokoero, jos haluat. int[] t1 = i1.getRGB(0, 0, w, h, null, 0, w); int[] t2 = i2.getRGB(0, 0, w, h, null, 0, w); long summa = 0, maksimi = 0; boolean huomioiLäpinäkyvyys = false; for (int i = 0; i < t1.length; ++i) { if (huomioiLäpinäkyvyys) { summa += Math.abs(((t1[i] >> 24) & 255) - ((t2[i] >> 24) & 255)); maksimi += 255; } summa += Math.abs(((t1[i] >> 16) & 255) - ((t2[i] >> 16) & 255)); maksimi += 255; summa += Math.abs(((t1[i] >> 8) & 255) - ((t2[i] >> 8) & 255)); maksimi += 255; summa += Math.abs(( t1[i] & 255) - ( t2[i] & 255)); maksimi += 255; } double ero = summa / (double) maksimi; System.out.format("Eroa on %.2f %%.\n", ero * 100);
Pystyykö tekemään simukan joka ottaa kahdesta (tai yhdestä ja kuvasta) videosta molemmista yhden kuvan kerrallaan ja sitten laskee niiden erojen keskiarvon? Ai niin, boolean ei bool. :D
Tässä versio jossa vastaus voidaan lisätä ikkunaan:
package imagebrain; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import java.text.DecimalFormat; import javax.swing.*; public class ImageBrain { public static void main (String args []) throws IOException{ String sijainti1 = null; String sijainti2; int pituus = 0; int pituus2 = 0; sijainti1= JOptionPane.showInputDialog( "Tämä ohjelma laskee kuvien eron ymmärettävään muotoon. \n" + "Jos kuvia ei löydy, ohjelma sulkeutuu. \n" + "Anna ensimmäisen kuvan sijainti levyllä:"); sijainti2= JOptionPane.showInputDialog( "Anna toisen kuvan sijainti:"); BufferedImage i1, i2; i1 = ImageIO.read(new File(sijainti1)); i2 = ImageIO.read(new File(sijainti2)); int w = Math.min(i1.getWidth(), i2.getWidth()); int h = Math.min(i1.getHeight(), i2.getHeight()); // TODO: Huomioi kuvien kokoero, jos haluat. int[] t1 = i1.getRGB(0, 0, w, h, null, 0, w); int[] t2 = i2.getRGB(0, 0, w, h, null, 0, w); long summa = 0, maksimi = 0; boolean huomioiLäpinäkyvyys = false; for (int i = 0; i < t1.length; ++i) { if (huomioiLäpinäkyvyys) { summa += Math.abs(((t1[i] >> 24) & 255) - ((t2[i] >> 24) & 255)); maksimi += 255; } summa += Math.abs(((t1[i] >> 16) & 255) - ((t2[i] >> 16) & 255)); maksimi += 255; summa += Math.abs(((t1[i] >> 8) & 255) - ((t2[i] >> 8) & 255)); maksimi += 255; summa += Math.abs(( t1[i] & 255) - ( t2[i] & 255)); maksimi += 255; } double ero = summa / (double) maksimi; DecimalFormat desimaalit = new DecimalFormat("0.00"); double tulos = ero * 100; String tulos2 = desimaalit.format(tulos); System.out.println(tulos2); JOptionPane.showMessageDialog(null, tulos2); } }
TVdata kirjoitti:
Pystyykö tekemään simukan joka ottaa kahdesta (tai yhdestä ja kuvasta) videosta molemmista yhden kuvan kerrallaan ja sitten laskee niiden erojen keskiarvon?
No eikö vastaus tuohon ole itsestäänselvä? Vai oliko sinulla joku syy epäillä, että ei pystyisi?
No sanotaan sitten noin. Millainen koodi ottaaa kuvia videosta silmukassa, vertaa toiseen videoon / kuvaan ja laskee sitten tulosten keskiarvon?
Mod. huom: sano uudessa viestissä äläkä lisäile monta tuntia vanhoihin viesteihin!
Yleisesti ottaen tuo varmaankin tapahtuisi käyttämällä valmista videokodekkia ja pyytämällä sitä purkamaan haluttu ruutu muistiin. Sitten sama toiselle videolle ja tämän jälkeen vaan jo läpikäydyllä tavalla vertailee näitä kahta kuvaa.
Videokodekkien käyttämisestä Javassa löytynee tietoja netistä.
Aihe on jo aika vanha, joten et voi enää vastata siihen.