Tutorials Infos - Anleitungen - Hilfe - Dreamcodes
 

Bildmanipulation

Ich habe 4 Algorithmen zur nachträglichen Bearbeitung von Bildern in PHP implementiert. Eigentlich sollten es noch mehr werden, aber PHP erwies sich als erheblich zu langsam für diese Aufgabe, trotzdem können sie gerne ausprobiert werden.

Salt & Pepper
Fügt einem Bild Schwarz-Weisses-Störrauschen hinzu. Dient hauptsächlich dazu die drei anderen Algorithmen zu testen.

Median
Ein sehr effektiver und schneller Algorithmus zum Entfernen von Rauschen in einem Bild

Meanvalue
Mittelwertfilter - bildet für jeden Pixel den Mittelwert der Umgebenden und entfernt so Rauschen. Nicht sonderlich effektiv, der Algorithmus gehört aber zum Standardrepertoire.

weighted Meanvalue
Das gleiche wie der Obige, nur werden die umgebenden Punkte anhand ihrer Entfernung zum zentralen Punkt gewichtet, was bessere Ergebnisse erziehlt.

Habe noch ein paar Funktionen zur Farbanpassung hinzugefügt, die man aufgrund ihrer Geschwindigkeit auch wirklich verwenden kann.

GrayScale
Erstellt ein Graustufenbild aus dem Bild. Die gewichtung der Farben ist anpassbar.

GammaCorrect
Gammakorrektur mithilfe der Funktion aus der gdlib.

Colorize
Veränderung der Farbe des Bildes.

Da man häufiger Bilder in ihrer Größe ändern muss habe ich dazu auch noch die Funktion Scale in der Kategorie Transformation eingefügt.

Script:

<?php
036:    /**
037: //  * Anwendungsbeispiel
038: //  **
039:
040: // Die Algorithmen zur Rauschentfernung koennen sehr lange dauern
041: set_time_limit(0);
042:
043: // Bild der Bibliothek uebergeben
044: $im = new ImageLibrary(imageCreateFromJPEG('test.jpg'));
045:
046: // Bild auf maximalgroesse 200 * 200 skalieren
047: $im->Transformation->Scale(200, 200);
048:
049: // Rauschen hinzufuegen
050: $im->NoiseReduction->SaltAndPepper();
051:
052: // Rauschen entfernen
053: $im->NoiseReduction->WeightedMeanValue();
054:
055: // Bild in Graustufenbild umwandeln
056: $im->ColorTransformation->GrayScale();
057:
058: // Bild ausgeben
059: $im->dump();
060:
061: // */
062:
063:
class ImageLibrary {
064:
065:     
// Bilddaten
066:     
var $image;
067:     var
$width;
068:     var
$height;
069:     
070:     
// Subklassen
071:     
var $NoiseReduction;
072:     var
$ColorTransformation;
073:     var
$Transformation;
074:     
075:     
/**
076:     * @return ImageLibrary
077:     * @param image $image
078:     * @desc Konstruktor und damit Initialisierung der
Bildbearbeitungsbibliothek
079:     */
080:     
function ImageLibrary(&$image) {
081:         
$this->data($image);
082:         
083:         
// Initialisieren der Untergruppen
084:         
$this->NoiseReduction = new NoiseReduction($this->image);
085:         
$this->ColorTransformation = new ColorTransformation($this->image);
086:         
$this->Transformation = new Transformation($this->image);
087:     }
088:     
089:     
/**
090:     * @return void
091:     * @param image $image
092:     * @desc Speichert die Bilddaten im Objekt
093:     */
094:     
function data(&$image) {
095:         
$this->image = &$image;
096:
097:         
$this->width = imageSx($this->image);
098:         
$this->height = imageSy($this->image);
099:     }
100:     
101:     
/**
102:     * @return void
103:     * @desc Gibt ein PNG aus inclusive Contenttype zur direkten
Darstellung im Browser aus
104:     */
105:     
function Dump() {
106:         
header("Content-type: image/png");
107:         
ImagePNG($this->image);
108:     }
109: }
110:
111: class
NoiseReduction extends ImageLibrary {
112:
113:     
/**
114:     * @return NoiseReduction
115:     * @param image $image
116:     * @desc Konstruktor
117:     */
118:     
function NoiseReduction(&$image) {
119:         
$this->data($image);
120:         
// Initialisierung des Zufallsgenerators
121:         
mt_srand((double)microtime()*1000000);
122:     }
123:
124:     
/**
125:     * @return void
126:     * @param integer $frequency
127:     * @param integer $intensity
128:     * @desc Legt ein Schwarz-Weiss-Rauschen ueber das Bild
129:     */
130:     
function SaltAndPepper($frequency = 5, $intensity = 100) {
131:         
$this->data($this->image);
132:         
// Anpassugn der Frequenz
133:         
$frequency = pow($frequency / 100, 2) * 100;
134:         
135:         
// Iterieren ueber das Bild
136:         
for ($i = 0; $i < $this->width; $i++) {
137:             for (
$j = 0; $j < $this->height; $j++) {
138:                 
139:                 
// Rauschen setzen?
140:                 
if ($frequency > mt_rand(0, 100)) {
141:                     
142:                     
// Farbe holen
143:                     
$color = imageColorsForIndex($this->image,
imageColorAt($this->image, $i, $j));
144:                     
// Intensitaet zufaellig bestimmen
145:                     
$add = mt_rand(intval($intensity * -2.55),
intval($intensity * 2.55));
146:                     
// Neue Farbe ermitteln
147:                     
$r = max( min($color['red'] + $add, 255), 0);
148:                     
$g = max( min($color['green'] + $add, 255), 0);
149:                     
$b = max( min($color['blue'] + $add, 255), 0);
150:                     
// Pruefen, ob die Farbe existiert, sonst neu in die
Farbtabelle einfuegen
151:                     
$color = imageColorExact($this->image, $r, $g, $b);
152:                     if (
$color == -1) {
153:                         
$color = imageColorAllocate($this->image, $r, $g,
$b);
154:                     }
155:                     
// Pixel schreiben
156:                     
imageSetPixel($this->image, $i, $j, $color);
157:                 }
158:             }
159:         }
160:     }
161:     
162:     
/**
163:     * @return void
164:     * @param integer $size
165:     * @desc Medianfilter
166:     */
167:     
function Median($size = 3) {
168:         
$this->data($this->image);
169:         
// Iterieren ueber das Bild
170:         
for ($i = 0; $i < $this->width; $i++) {
171:             for (
$j = 0; $j < $this->height; $j++) {
172:                 
// Den Pixel umgebende Punkte eindsammeln
173:                 
$points = array();
174:                 for (
$k = max(0, $i - intval(($size - 1) / 2)); $k <
min($this->width, $i + intval(($size - 1) / 2)); $k++) {
175:                     for (
$l = max(0, $j - intval(($size - 1) / 2)); $l <
min($this->height, $j + intval(($size - 1) / 2)); $l++) {
176:                         
$color = imageColorsForIndex($this->image,
imageColorAt($this->image, $k, $l));
177:                         
// Grauwer und Position im Array speichern
178:                         
$points[0][] = ($color['red'] + $color['green'] +
$color['blue']);
179:                         
$points[1][] = $k;
180:                         
$points[2][] = $l;
181:                     }
182:                 }
183:                 
// Punkteliste ihrem Grauwert nach sortieren
184:                 
array_multisort($points[0], SORT_NUMERIC, SORT_ASC,
$points[1], $points[2]);
185:                 
// Den Wert des mittleren Punktes nehmen und als neue
Farbe setzen
186:                 
ImageSetPixel($this->image, $i, $j,
imageColorAt($this->image, $points[1][floor(count($points[0]) / 2)],
$points[2][floor(count($points[0]) / 2)]));
187:             }
188:         }
189:     }
190:     
191:     
/**
192:     * @return void
193:     * @param unknown $size
194:     * @desc Mittelwertfilter
195:     */
196:     
function MeanValue($size = 3) {
197:         
$this->data($this->image);
198:         
// Iterieren ueber das Bild
199:         
for ($i = 0; $i < $this->width; $i++) {
200:             for (
$j = 0; $j < $this->height; $j++) {
201:                 
// Um den Mittelwert zu Bilden alle umgebenden Punkte
aufaddieren
202:                 
$r = 0;
203:                 
$g = 0;
204:                 
$b = 0;
205:                 
$c = 0;
206:                 for (
$k = max(0, $i - intval(($size - 1) / 2)); $k <
min($this->width, $i + intval(($size - 1) / 2)); $k++) {
207:                     for (
$l = max(0, $j - intval(($size - 1) / 2)); $l <
min($this->height, $j + intval(($size - 1) / 2)); $l++) {
208:                         
$color = imageColorsForIndex($this->image,
imageColorAt($this->image, $k, $l));
209:                         
$r += $color['red'];
210:                         
$g += $color['green'];
211:                         
$b += $color['blue'];
212:                         
$c++;
213:                     }
214:                 }
215:                 
// Arithmetisches Mittel: Teilen durch die Anzahl der
Punkte
216:                 
$r = round($r / $c);
217:                 
$g = round($g / $c);
218:                 
$b = round($b / $c);
219:                 
// Pruefen, ob die Farbe existiert, sonst neu in die
Farbtabelle einfuegen
220:                 
$color = imageColorExact($this->image, $r, $g, $b);
221:                 if (
$color == -1) {
222:                     
$color = imageColorAllocate($this->image, $r, $g, $b);
223:                 }
224:                 
// Pixel schreiben
225:                 
imageSetPixel($this->image, $i, $j, $color);
226:             }
227:         }
228:     }
229:
230:     
/**
231:     * @return void
232:     * @desc Gewichteter Mittelwertfilter fuer die 3x3-Maske
233:     */
234:     
function WeightedMeanValue() {
235:         
$this->data($this->image);
236:         
// Iterieren ueber das Bild
237:         
for ($i = 0; $i < $this->width; $i++) {
238:             for (
$j = 0; $j < $this->height; $j++) {
239:                 
$r = 0;
240:                 
$g = 0;
241:                 
$b = 0;
242:                 
$c = 0;
243:                 
// Um den Mittelwert zu Bilden alle umgebenden Punkte
gewichtet
244:                 // nach dem Abstand zum Mittelpunkt aufaddieren
245:                 
for ($k = max(0, $i - 1); $k < min($this->width, $i + 2);
$k++) {
246:                     for (
$l = max(0, $j - 1); $l < min($this->height, $j +
2); $l++) {
247:                         
$color = imageColorsForIndex($this->image,
imageColorAt($this->image, $k, $l));
248:                         switch (
abs($k - $i) + abs($l - $j)) {
249:                             case
0:
250:                                 
$r += 4 * $color['red'];
251:                                 
$g += 4 * $color['green'];
252:                                 
$b += 4 * $color['blue'];
253:                                 
$c += 4;
254:                             break;
255:                             case
1:
256:                                 
$r += 2 * $color['red'];
257:                                 
$g += 2 * $color['green'];
258:                                 
$b += 2 * $color['blue'];
259:                                 
$c += 2;
260:                             break;
261:                             case
2:
262:                                 
$r += $color['red'];
263:                                 
$g += $color['green'];
264:                                 
$b += $color['blue'];
265:                                 
$c ++;
266:                             break;
267:                             default:
268:                                 
printf("Diffs: %d, %d; %d %d - %d %d\n",
abs($k - $i), abs($l - $j), $i, $j, $k, $l);
269:                         }
270:                     }
271:                 }
272:                 
// Teilen durch die "Gesammtpunktezahl"
273:                 
$r = round($r / $c);
274:                 
$g = round($g / $c);
275:                 
$b = round($b / $c);
276:                 
// Pruefen, ob die Farbe existiert, sonst neu in die
Farbtabelle einfuegen
277:                 
$color = imageColorExact($this->image, $r, $g, $b);
278:                 if (
$color == -1) {
279:                     
$color = imageColorAllocate($this->image, $r, $g, $b);
280:                 }
281:                 
// Pixel schreiben
282:                 
imageSetPixel($this->image, $i, $j, $color);
283:             }
284:         }
285:     }
286: }
287:
288: class
ColorTransformation extends ImageLibrary {
289:     
290:     
/**
291:     * @return ColorTransformation
292:     * @param image $image
293:     * @desc Konstruktor
294:     */
295:     
function ColorTransformation (&$image) {
296:         
$this->data($image);
297:     }
298:     
299:     
/**
300:     * @return void
301:     * @param float $rg
302:     * @param float $gg
303:     * @param float $bg
304:     * @desc Graustufenbild entsprechend der angegebenen Farbgewichtung
305:     */
306:     
function GrayScale ($rg = 0.4, $gg = 0.35, $bg = 0.25) {
307:         
$this->data($this->image);
308:         
// Iterieren ueber das Bild
309:         
for ($i = 0; $i < $this->width; $i++) {
310:             for (
$j = 0; $j < $this->height; $j++) {
311:                 
$color = imageColorsForIndex($this->image,
imageColorAt($this->image, $i, $j));
312:                 
// graustufenwert fuer Pixel berechnen
313:                 
$gray = max( min($color['red'] * $rg + $color['green'] *
$gg + $color['blue'] * $bg, 255), 0);
314:                 
// Pruefen, ob die Farbe existiert, sonst neu in die
Farbtabelle einfuegen
315:                 
$color = imageColorExact($this->image, $gray, $gray,
$gray);
316:                 if (
$color == -1) {
317:                     
$color = imageColorAllocate($this->image, $gray, $gray,
$gray);
318:                 }
319:                 
// Pixel schreiben
320:                 
imageSetPixel($this->image, $i, $j, $color);
321:             }
322:         }
323:     }
324:     
325:     
/**
326:     * @return void
327:     * @param float $gamma
328:     * @desc Gammakorrektur
329:     */
330:     
function GammaCorrect ($gamma) {
331:         
$this->data($this->image);
332:         
imagegammacorrect($this->image, 1, $gamma);
333:     }
334:
335:     
/**
336:     * @return void
337:     * @param float $rg
338:     * @param float $gg
339:     * @param float $bg
340:     * @desc Farbaenderungen am Bild
341:     */
342:     
function Colorize ($rg = 1, $gg = 1, $bg = 1) {
343:         
$this->data($this->image);
344:         
// Iterieren ueber das Bild
345:         
for ($i = 0; $i < $this->width; $i++) {
346:             for (
$j = 0; $j < $this->height; $j++) {
347:                 
$color = imageColorsForIndex($this->image,
imageColorAt($this->image, $i, $j));
348:                 
// Neue Farbwerte berechnen
349:                 
$r = max( min($color['red'] * $rg, 255), 0);
350:                 
$g = max( min($color['green'] * $gg, 255), 0);
351:                 
$b = max( min($color['blue'] * $bg, 255), 0);
352:                 
// Pruefen, ob die Farbe existiert, sonst neu in die
Farbtabelle einfuegen
353:                 
$color = imageColorExact($this->image, $r, $g, $b);
354:                 if (
$color == -1) {
355:                     
$color = imageColorAllocate($this->image, $r, $g, $b);
356:                 }
357:                 
// Pixel schreiben
358:                 
imageSetPixel($this->image, $i, $j, $color);
359:             }
360:         }
361:     }
362: }
363:
364: class
Transformation extends ImageLibrary {
365:     
366:     
/**
367:     * @return Transformation
368:     * @param image $image
369:     * @desc Konstruktor
370:     */
371:     
function Transformation (&$image) {
372:         
$this->data($image);
373:     }
374:     
375:     
/**
376:     * @return void
377:     * @param integer $maxwidth
378:     * @param integer $maxheight
379:     * @desc Scaliert ein Bild proportional mit neuer Maximalbreite und
-hoehe
380:     */
381:     
function Scale($maxwidth, $maxheight) {
382:         
$this->data($this->image);
383:         
// Skalierungsfaktoren berechnen
384:         
$xFactor = $this->width / $maxwidth;
385:         
$yFactor = $this->height / $maxheight;
386:         
387:         
// Groessere noetige Skalierung verwenden
388:         
if ($xFactor > $yFactor) {
389:             
$newwidth = $maxwidth;
390:             
$newheight = $this->height / $xFactor;
391:         } else {
392:             
$newwidth = $this->width / $yFactor;
393:             
$newheight = $maxheight;
394:         }
395:         
396:         
// Zielbild erstellen
397:         
$dst = imagecreatetruecolor($newwidth, $newheight);
398:         
// Bild kopieren
399:         
imagecopyresampled($dst, $this->image, 0, 0, 0, 0, $newwidth,
$newheight, $this->width, $this->height);
400:         
401:         
// Zielbild fuer zukuenftiges verwenden
402:         
imagedestroy($this->image);
403:         
$this->image = $dst;
404:         
$this->data($this->image);
405:     }
406: }
407:
?>

 
ID: 585
eingestellt am: 05.01.2005
Autor: NA
Status zum lesen: Gast
gelesen: 13373
Webseite: www.dreamcodes.com
[Drucken]