2017-03-28 3 views
2

Ich möchte einen Algorithmus in Python erstellen, um ein Bild in N-mal-N gleiche Blöcke zu schneiden. Ich kenne vorhandene Python-Pakete, die das können, aber ich bin daran interessiert, mathematische Berechnungen unter Verwendung der Dimensionen der resultierenden Blöcke durchzuführen, die keine ganzzahligen Werte sein müssen.Slicing NDarray mit Schwimmern in Python

Ich habe erfolgreich meine Bildeingabe in ndarray mit numpy und cv2 konvertiert. Ich bin neugierig, ob ich ein ndarray Objekt in einer Weise schneiden kann, dass, wenn ich ein "Pixel" aufspalte, ich einfach den gewichteten Durchschnitt dieses "Pixel" Beitrags zu ihrem jeweiligen Block nehme.

Wenn beispielsweise die Bildeingabe die Abmessungen 100px x 100px hat und ich dieses Bild in 7x7 Blöcke aufteilen möchte, da 100/7 = ~ 14.2857, hat jeder Block die Abmessungen 14.2857 x 14.2857. Aber es macht keinen Sinn, einen Bruchteil eines Pixels zu haben. Stattdessen möchte ich dies so interpretieren, dass der erste Block alle Informationen aus den Pixeln (1,1), (1,2), ..., (1,14), (2,1), ... enthält. , (3,1), ..., (14,1), ..., (14,14), 0,2857 aller Pixel, die (15, k) und (k, 15) erfüllen, und 0,2857 * 0,2857 für das Pixel (15,15). Ich möchte dies für alle 49 Blöcke tun.

Jeder Einblick würde geschätzt werden! Vielen Dank.

Antwort

1

Wie Sie richtig festgestellt haben, können Sie nicht 14,29 Pixel in einem Bild haben. Sie können jedoch Downsampling auf 14 (oder weniger) Pixel oder Upsampling auf 15 (oder mehr) Pixel ausführen. Ich denke, ersteres ist das, was Sie vorhaben, aber letzteres ist auch eine praktikable Option.

Ein einfacher Ansatz besteht darin, das Bild auf eine neue Größe zu skalieren, die problemlos in 7x7 aufgeteilt werden kann. Wenn Sie die richtige Funktion dazu verwenden (z. B. scipy.ndimage.interpolation.zoom), interpoliert es automatisch Pixelwerte.

Der Einfachheit halber nehmen wir an, Sie 5x5 Bild in 2x2 Blöcke geteilt werden soll:

from scipy.ndimage.interpolation import zoom 
import numpy as np 

blocks = (2, 2) 

image = np.arange(25).reshape(5, 5) * 10 
print(image) 
# [[ 0 10 20 30 40] 
# [ 50 60 70 80 90] 
# [100 110 120 130 140] 
# [150 160 170 180 190] 
# [200 210 220 230 240]] 

# use np.ceil instead of np.floor to do upsampling 
zoom_factor = [np.floor(s/b) * b/s for s, b in zip(image.shape, blocks)] 

zoomed = zoom(image, zoom_factor) 
print(zoomed) 
# [[ 0 14 26 40] 
# [ 69 83 95 109] 
# [131 145 157 171] 
# [200 214 226 240]] 

for b1 in range(0, zoomed.shape[0], blocks[0]): 
    for b2 in range(0, zoomed.shape[1], blocks[1]): 
     print('block:') 
     print(zoomed[b1:b1+blocks[0], :][:, b2:b2+blocks[1]]) 
# block: 
# [[ 0 14] 
# [69 83]] 
# block: 
# [[ 26 40] 
# [ 95 109]] 
# block: 
# [[131 145] 
# [200 214]] 
# block: 
# [[157 171] 
# [226 240]] 

Beachten Sie, dass das zweite Pixel in der ersten Zeile in dem gezoomten Bild einen Wert von 14 hat, die Beiträge von beiden neigbors enthält 10 und 20. (Es enthält wahrscheinlich auch einen Beitrag von anderen Pixeln, weil der Zoom standardmäßig einen Spline mit der Ordnung 3 für die Interpolation verwendet). Andere Pixel in der Mitte des Bildes enthalten Beiträge von der gesamten umliegenden Nachbarschaft.

+0

Vielen Dank für die Eingabe. Ich mag den Rat. Das einzige Problem, das ich mit diesem Ansatz bewältigen werde, ist der Vergleich von zwei Bildern unterschiedlicher Dimensionen, die das Gesamtziel meines Projekts sind. Was ist, wenn ich zwei Bilder von verschiedenen Dimensionen habe und die beiden vergleichen möchte? Sollte ich das größere Bild verkleinern, um es an die Abmessungen des kleineren Bildes anzupassen, und dann diesen Ansatz umsetzen? Danke für die Hilfe! – Wilson

+0

@wilson Im Allgemeinen, ja, das würde ich tun. Wenn ich mit vielen Bildern unterschiedlicher Größe arbeite, wähle ich normalerweise eine "Arbeitsgröße" und skaliere alle Bilder auf diese Größe. Kleinere Bilder werden upgesampelt und größere Bilder werden verkleinert. Wenn Sie kleinere Bilder verkleinern oder größere verkleinern, hängt dies von Ihrer Anwendung und Ihren Vorlieben ab. – kazemakase

+0

Vielen Dank für die Antwort. Glücklicherweise arbeite ich mit sehr großen Bildern, so dass diese Bilder verkleinert werden, um verschiedene Partitionsgrößen auszugleichen und die Qualität der Bilder beizubehalten, wird nicht viel Pixelinformation verlieren. Noch eine Frage: Wie erhält man das Seitenverhältnis der Bilder bei gleichzeitiger Anpassung der Abmessungen? – Wilson