Wie kann ich ein Bild mit einer Auflösung auf ein Viertel der Größe verkleinern, indem ich die Pixel in Numpy mittle?

Was ich durch Recherchen herausgefunden habe, funktioniert nur für Bilder, die quadratisch sind (d. H. 512 x 512 bis 128 x 128), aber nicht für Bilder mit unterschiedlichen Abmessungen (d. H. 2400 x 1800 bis 600 x 450). In diesen Fällen erhalte ich einen IndexError: Der Index 450 ist für Achse 1 mit der Größe 450 außerhalb der Grenzen.

Ich versuche, diese Aufgabe mit der Manipulation von Numpy-Arrays und ohne Installation anderer Pakete und Bibliotheken auszuführen.

Ich habe eine Funktion recherchiert

numpy.mean()

Aber ich weiß nicht, wie ich es in Bezug auf dieses Problem verwenden soll.

import cv2
import numpy as np

def quarter_res_avg(im):

    original_width = im.shape[1]
    original_height = im.shape[0]

    width = original_width / 4
    height = original_height / 4

    resized_image = np.zeros(shape=(width, height, 3), dtype=np.uint8)

    scale = 4

    for i in range(width):
        for j in range(height):
            temp = np.array([0, 0, 0])
            for x in range(scale):
                for y in range(scale):
                    temp += im[i*scale+x, j*scale+y]
            resized_image[i, j] = temp/(scale*scale)

    return resized_image

im = cv2.imread('Lenna_test_image.png', 1)
cv2.imwrite('Lenna_test_image_avg.png', quarter_res_avg(im))

Irgendwelche Ideen werden sehr geschätzt.

Vielen Dank.

0
Q2Learn 21 Feb. 2020 im 23:23

3 Antworten

Beste Antwort

Die Antwort, die bei mir mit Hilfe von @MarkSetchell in den Kommentaren der Frage funktioniert hat.

Ohne np.mean ()

def quarter_res_avg(im):

    original_width = im.shape[1]
    original_height = im.shape[0]
    width = original_width / 4
    height = original_height / 4

    resized_image = np.zeros(shape=(height, width, 3), dtype=np.uint8)
    scale = 4

    for i in range(height):
        for j in range(width):
            temp = np.array([0, 0, 0])
            for x in range(scale):
                for y in range(scale):
                    temp += im[i*scale + x, j*scale + y]
            resized_image[i, j] = temp/(scale*scale)

return resized_image

im = cv2.imread('Lenna_test_image.png', 1)
cv2.imwrite('Lenna_test_image_resized.png', quarter_res_avg(im))    

Ersetzen Sie mit np.mean () die for-Schleifen durch:

for i in range(0, original_height, scale):
    for j in range(0, original_width, scale):
        resized_image[i/scale, j/scale] = np.mean(im[i:i + scale, j:j+scale], axis=(0,1))
0
Q2Learn 28 Feb. 2020 im 04:31

Formen Sie zuerst Ihr M x N-Bild in ein (M // 4) x 4 x (N // 4) x 4-Array um und verwenden Sie dann np.mean in der zweiten und letzten Dimension.

from typing import Tuple
import numpy as np

def downsample_by_averaging(img: np.ndarray, window_shape: Tuple[int, int]) -> np.ndarray:
    return np.mean(
        img.reshape((
            *img.shape[:-2],
            img.shape[-2] // window_shape[-2], window_shape[-2],
            img.shape[-1] // window_shape[-1], window_shape[-1],
        )),
        axis=(-1, -3),
    )

downsample_by_averaging(img, (4, 4))
0
Maxpxt 21 Feb. 2020 im 20:45
import numpy as np
import skimage.measure

your_array = np.random.rand(2400, 800)

new_array = skimage.measure.block_reduce(your_array, (4,4), np.mean)
print(new_array.shape)
Out[18]: (600, 450)
2
Nicolas Gervais 21 Feb. 2020 im 20:33