[PYTHON] Digitale Bildverarbeitung (räumliche Filterung)

* Räumliche Filterung *

Es ist ein Bereich zur Pixeloperation. Auf jedes Pixel wird ein Filter angewendet, und eine Produktsummenoperation wird ausgeführt, um das Bild zu glätten (Rauschen zu entfernen) und Kanten zu erkennen. Wenden Sie für das Bild den Filter mit hoher Geschwindigkeit wie dieses Video an und geben Sie den vom Filter erhaltenen berechneten Wert in das Fallpixel ein. (Auch Falten genannt)

Glätten (Reduzieren von Ungleichmäßigkeiten der Pixelwerte)

* Zu verwendendes Bild *

1_av_fil_before.jpg

Bibliothek verwendet

python


import numpy as np
from numpy.lib.stride_tricks import as_strided
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import axes3d
import matplotlib.gridspec as gridspec
import seaborn as sns
import math
import cv2

* Mittelungsfilter *

Der Durchschnitt der Pixelwerte in der Region wird als Wert des interessierenden Pixels genommen.

python


av_filter = np.array([[ 1/25,1/25,1/25,1/25,1/25,],
                      [ 1/25,1/25,1/25,1/25,1/25,],
                      [ 1/25,1/25,1/25,1/25,1/25,],
                      [ 1/25,1/25,1/25,1/25,1/25,],
                      [ 1/25,1/25,1/25,1/25,1/25,]], np.float32)

# ddepth = -1, means destination image has depth same as input image
dst1 = cv2.filter2D(image_1, -1, av_filter)
cv2.imwrite('2_av_fil.jpg', dst1)

↓ Es wird insgesamt geglättet.

2_av_fil.jpg

* Gewichteter Durchschnittsfilter *

Wird auch als * gewichtete Mittelung * bezeichnet, eine Verteilung, die auf dem interessierenden Pixel zentriert ist, wobei das Gewicht nach außen hin abnimmt

python


add_av_fil = np.array([[1, 4, 6, 4, 1],
       [4, 16, 24, 16, 4],
       [6, 24, 36, 24, 6],
       [4, 16, 24, 16, 4],
       [1, 4, 6, 4, 1]], np.float32)/256

dst1 = cv2.filter2D(res, -1, add_av_fil)
cv2.imwrite('3_add_av_fil.jpg', dst1)

↓ Es ist relativ geglättet, während die Kanten erhalten bleiben.

3_add_av_fil.jpg

* Gaußscher Filter *

Gewichtet nach Gaußscher Verteilung.

h\left(x, y\right) = \frac{1}{2\pi\sigma^2}{\exp{\left(-\frac{x^2+y^2}{2\sigma^2}\right)}}\\

python


def gausian(X, y, siguma):
#     exp(-(x2 + y2)/2σ2)
    h2 = math.e**(-1*((X**2) + (y**2))/(2*(siguma**2)))
#     2πσ2
    h3 = 2*math.pi*(siguma**2)
    h = h2/h3
    return h

sns.set_style('ticks')

fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111, projection='3d')

x = y = np.arange(-3,3,0.1)
X,Y = np.meshgrid(x,y)

ax.plot_surface(X,Y, gausian(X,Y,1),cmap='coolwarm')
plt.show()
plt.savefig("gausian_fig.jpg ")

↓ Ein solches Bild

gausian_fig.jpg

Handgemacht

python


def gausian_kernel(size):
    if size%2==0:
        print('kernel size should be odd')
        return
    sigma = (size-1)/2
    
#     [0,size]→[-sigma, sigma]Verschiebung
    x = y = np.arange(0,size) - sigma
    X,Y = np.meshgrid(x,y) 
    print(sigma)
    
    mat = gausian(X,Y,sigma)
    
    #Damit ist die Summe 1
    kernel = mat / np.sum(mat)
    return mat

g_fil_hand = gausian_kernel(3)

#Filterform
#[[0.05854983 0.09653235 0.05854983]
#[0.09653235 0.15915494 0.09653235]
#[0.05854983 0.09653235 0.05854983]]

dst1 = cv2.filter2D(res, -1, g_fil_hand)
cv2.imwrite('4_g_hand_fil.jpg', dst1)

4_g_hand_fil.jpg

von opencv

python


sigma = 2
blur = cv2.GaussianBlur(res, (0, 0), sigmaX = 3, sigmaY = 3)
cv2.imwrite('5_g_cv_fil.jpg', blur)

5_g_cv_fil.jpg

* Glätten in eine bestimmte Richtung *

Mit den folgenden Filtern wird die Glättung nur in einer bestimmten Richtung durchgeführt. Das Bild sieht aus, als wäre es seitwärts geschüttelt.

python


flat_d_fil = np.zeros([15, 15])

for i in range(15):
    flat_d_fil[i, i] = 1/15

dst1 = cv2.filter2D(res, -1, flat_d_fil)
cv2.imwrite('6_shaky_fil.jpg', dst1)

6_shaky_fil.jpg

* Differenzfilter *

Für vertikale Kanten

python


diff_col = np.array([[0, 0, 0],
        [1, 0, -1],
        [0, 0, 0]])

dst1 = cv2.filter2D(res, -1, 8*diff_col)
cv2.imwrite('7_diff_col.jpg', dst1)

7_diff_col.jpg

Für horizontale Kanten

python


diff_row = np.array([[0, -1, 0],
        [0, 0, 0],
        [0, 1, 0]])

dst1 = cv2.filter2D(res, -1, 8*diff_row)
cv2.imwrite('8_diff_row.jpg', dst1)

8_diff_row.jpg

* Pruwit Filter *

Kombination aus Differenzialfilter und Durchschnittsfilter Nehmen Sie den Gradienten des Pixelwerts in horizontaler Richtung auf + Glätten Sie den Gradienten des Pixelwerts in vertikaler Richtung

python


pulu_fil = np.array([[1, 0, -1],
        [1, 0, -1],
        [1, 0, -1]])

dst1 = cv2.filter2D(res, -1, 2*pulu_fil)
cv2.imwrite('9_pulu_fil.jpg', dst1)

9_pulu_fil.jpg

* Sobel Filter *

Kombination aus Differenzialfilter und gewichtetem Durchschnittsfilter Erzielt einen gleichmäßigeren Unschärfegrad als Pruwitt. Nehmen Sie den Gradienten des Pixelwerts in horizontaler Richtung auf + Glätten Sie den Gradienten des Pixelwerts in vertikaler Richtung

python


sobel_fil = np.array([[1, 0, -1],
        [2, 0, -2],
        [1, 0, -1]])

dst1 = cv2.filter2D(res, -1, sobel_fil)
cv2.imwrite('10_sobel_fil.jpg', dst1)

10_sobel_fil.jpg

* Differentialfilter zweiter Ordnung *

Gefühl, dass der Differentialfilter verdoppelt ist

python


todiff_fil = np.array([[0, 0, 0],
                      [1, -2, 1],
                      [0, 0, 0]])

dst1 = cv2.filter2D(res, -1, 2*todiff_fil)
cv2.imwrite('11_to_diff_fil.jpg', dst1)

* Laplace-Filter *

Es fühlt sich an wie die Vertikale + Horizontale des quadratischen Differentials.

python


lap_fil = np.array([[0, 1, 0],
        [1, -4, 1],
        [0, 1, 0]])

dst1 = cv2.filter2D(res,ddepth=cv2.CV_16S,kernel=lap_fil)
cv2.imwrite('12_lap_hand_fil.jpg', dst1+100)

plt.plot(ds[400])
plt.savefig("lap_fig_1.jpg ")

12_lap_fil.jpg

lap_fig_1.jpg

mit opencv

python


ddepth = cv2.CV_16S
kernel_size = 3
dst = cv2.Laplacian(res, ddepth, ksize=kernel_size)
cv2.imwrite('13_lap_cv_fil.jpg', dst)

plt.plot(dst[400]+100)
plt.savefig("lap_fig_2.jpg ")

13_lap_cv_fil.jpg

* Protokollfilter (Laplace-Gauß-Filter) *

h\left(x, y\right) = \frac{x^2+y^2-2\sigma^2}{2\pi\sigma^6}{\exp{\left(-\frac{x^2+y^2}{2\sigma^2}\right)}}\\

Handgemacht

python


def Log_fil(X, y, siguma):
    
#     X2+y2-2σ2
    h1 = ((X**2) + (y**2) - (2*(siguma**2))) 
    
#     exp(-(x2 + y2)/2σ2)
    h2 = math.e**(-1*((X**2) + (y**2))/(2*(siguma**2)))
    
#     2πσ6
    h3 = 2*math.pi*(siguma**6)

    h = h1*h2/h3
    return h

sns.set_style('ticks')

fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111, projection='3d')

x = y = np.arange(-3,3,0.1)
X,Y = np.meshgrid(x,y)

ax.plot_surface(X,Y,Log_fil(X,Y,1),cmap='coolwarm')
plt.savefig("log_fig.jpg ")
plt.show()

log_fig.jpg

python


def L_of_g_kernel(size, sigma):
    if size%2==0:
        print('kernel size should be odd')
        return
    ad_size = (size-1)/2
    
    # [0,size]→[-sigma, sigma]Verschiebung
    x = y = np.arange(0,size) - ad_size
    X,Y = np.meshgrid(x,y) 
    print(sigma)
    
    mat = Log_fil(X,Y,sigma)
    print(mat)
    
    #Damit ist die Summe 0
    kernel = mat - np.sum(mat)/size**2
    
    return kernel

log_fil =  L_of_g_kernel(5, 1)

#Filterform
#[[ 0.01749015  0.0391927   0.04307856  0.0391927   0.01749015]
# [ 0.0391927   0.         -0.09653235  0.          0.0391927 ]
# [ 0.04307856 -0.09653235 -0.31830989 -0.09653235  0.04307856]
# [ 0.0391927   0.         -0.09653235  0.          0.0391927 ]
# [ 0.01749015  0.0391927   0.04307856  0.0391927   0.01749015]]

python


dst1 = cv2.filter2D(res,ddepth=cv2.CV_16S,kernel=log_fil)
cv2.imwrite('14_log_fil_hand.jpg', dst1*20+200)
plt.savefig("log_fill_1.jpg ")
plt.plot(dst1[400]*20+200)

14_log_fil_hand.jpg

log_fill_1.jpg

von opencv

python


ddepth = cv2.CV_16S
kernel_size = 5

# Apply Gaussian Blur
blur = cv2.GaussianBlur(res,(5, 5), sigmaX = 1, sigmaY = 1)

# Apply Laplacian operator in some higher datatype
dst = cv2.Laplacian(blur, ddepth, ksize=kernel_size)
cv2.imwrite('15_log_fil_cv.jpg', dst+200)

plt.plot(dst[400])
plt.savefig("log_fill_2.jpg ")

15_log_fil_cv.jpg

log_fill_2.jpg

Extraktion von 0 Kreuzungen

python


def Zero_crossing(image, thresh):
    z_c_image = np.zeros(image.shape)
    
    # For each pixel, count the number of positive
    # and negative pixels in the neighborhood
    
    for i in range(1, image.shape[0] - 1):
        for j in range(1, image.shape[1] - 1):
            negative_count = 0
            positive_count = 0
            neighbour = [image[i+1, j-1],image[i+1, j],image[i+1, j+1],image[i, j-1],image[i, j+1],image[i-1, j-1],image[i-1, j],image[i-1, j+1]]
            d = max(neighbour)
            e = min(neighbour)
            for h in neighbour:
                if h>0:
                    positive_count += 1
                elif h<0:
                    negative_count += 1
 
 
            # If both negative and positive values exist in 
            # the pixel neighborhood, then that pixel is a 
            # potential zero crossing
            
            z_c = ((negative_count > 0) and (positive_count > 0) and (d-e > thresh))
            
            # Change the pixel value with the maximum neighborhood
            # difference with the pixel
 
            if z_c:
                z_c_image[i, j] = 200

 
    return z_c_image

dst2 = Zero_crossing(dst1, 10)
cv2.imwrite('16_log_fil_zero.jpg', dst2)

16_log_fil_zero.jpg

* Erkennung durch Canny *

1, glätten

Glätten mit Gauß-Filter

2, Verarbeitung durch vertikale und horizontale Differentialfilter

Sie verwenden den Sobel-Filter.

3, Berechnung des Gradientenbetrags und der Gradientenrichtung

M(x,y) = \sqrt{G_x^2+G_y^2}
\Theta = atan2 \left(G_y/G_x \right)

4, Schwellenwertverarbeitung

Es wird nur ein bestimmter Bereich erkannt, um falsch positive Ergebnisse zu entfernen.

python


class Canny_hand:
    def __init__(self, image, sigma, h_thresh, l_thresh):
        self.image = image.astype(np.float32)#Datentypspezifikation
        self.h, self.w = image.shape
        self.sigma = sigma
        self.h_thresh = h_thresh
        self.l_thresh = l_thresh
        self.sobelx = np.array([[-1, 0, 1],
                          [-2, 0, 2],
                          [-1, 0, 1]])

        self.sobely = np.array([[-1, -2, -1],
                          [0,  0, 0],
                          [1, 2, 1]])

    def do(self,):
        blur = cv2.GaussianBlur(self.image,(0, 0),  sigmaX = self.sigma, sigmaY = self.sigma)
        Gx = cv2.filter2D(blur, -1, self.sobelx)
        Gy = cv2.filter2D(blur, -1, self.sobely)
        G_value = np.sqrt(np.square(Gy) + np.square(Gx)) 
        G_angle = np.arctan2(Gy, Gx)
        G_angle_set = self.set_angle(G_angle)
        G_max_group = self.extract_max(G_value, G_angle_set)
        result = self.thresh_hold(G_max_group, min=self.l_thresh, max=self.h_thresh)

        return result

    def set_angle(self, G_angle):
        pai = math.pi
        
        G_angle[np.where((G_angle >= -pai/8) & (G_angle < pai/8))] = 0
        G_angle[np.where((G_angle >= pai/8) & (G_angle < 3*pai/8))] = 45
        G_angle[np.where((G_angle >= 3*pai/8) & (G_angle < 5*pai/8))] = 90
        G_angle[np.where((G_angle >= 5*pai/8) & (G_angle < 7*pai/8))] = 135
        G_angle[np.where((G_angle >= 7*pai/8) & (G_angle < -7*pai/8))] = 180
        G_angle[np.where((G_angle >= -7*pai/8) & (G_angle < -5*pai/8))] = 225
        G_angle[np.where((G_angle >= -5*pai/8) & (G_angle < -3*pai/8))] = 270
        G_angle[np.where((G_angle >= -3*pai/8) & (G_angle < -pai/8))] = 315

        return G_angle

    def extract_max(self, G_value, G_angle_set):
        result = G_value.copy()

        for y in range(1, self.h - 1):
            for x in range(1, self.w - 1):

                if G_angle_set[y][x] == 0:
                    if (G_value[y][x] < G_value[y][x+1]):
                        result[y][x] = 0
                elif G_angle_set[y][x] == 45:
                    if (G_value[y][x] < G_value[y+1][x+1]):
                        result[y][x] = 0
                elif G_angle_set[y][x] == 90:
                    if (G_value[y][x] < G_value[y+1][x]):
                        result[y][x] = 0
                elif G_angle_set[y][x] == 135:
                    if (G_value[y][x] < G_value[y+1][x-1]):
                        result[y][x] = 0
                elif G_angle_set[y][x] == 180:
                    if (G_value[y][x] < G_value[y][x-1]):
                        result[y][x] = 0
                elif G_angle_set[y][x] == 225:
                    if (G_value[y][x] < G_value[y-1][x-1]):
                        result[y][x] = 0
                elif G_angle_set[y][x] == 270:
                    if (G_value[y][x] < G_value[y-1][x]):
                        result[y][x] = 0
                elif G_angle_set[y][x] == 315:
                    if (G_value[y][x] < G_value[y-1][x+1]):
                        result[y][x] = 0

        return result

    def thresh_hold(self, in_put, min=75, max=150, d=1):

        for y in range(0, self.h):
            for x in range(0, self.w):

                if in_put[y][x] >= max:
                    in_put[y][x] = 255

                elif in_put[y][x] < min:
                    in_put[y][x] = 0

                else:
                    if np.max(in_put[y-d:y+d+1, x-d:x+d+1]) >= max:
                        in_put[y][x] = 255
                    else:
                        in_put[y][x] = 0

        return in_put

canny = Canny_hand(res, 0.3,100, 200 )
can_do = canny.do()
cv2.imwrite('17_canny_hand.jpg', can_do)

17_canny_hand.jpg

von opencv

python


edges = cv2.Canny(res,0.3,  100, 200)
cv2.imwrite('17_canny.jpg', dst2)

17_canny.jpg

* Schärfen *

Originalbild + (Originalbild-Bild nach dem Glätten) x Konstante

python


# Apply Gaussian Blur
blur = cv2.GaussianBlur(res,(0, 0), sigmaX = 3, sigmaY = 3)
cv2.imwrite('shap_blur.jpg', blur)

diff = res - blur
cv2.imwrite('18_shape_diff.jpg', diff)

shapen = res + diff*3
cv2.imwrite('19_shape_shapen.jpg', shapen)

shap_blur.jpg 18_shape_diff.jpg 19_shape_shapen.jpg

* Lokale Mittelung *

Sie kann gemittelt werden, während relativ Kanten übrig bleiben. Als Beispiel werden die folgenden 9 Muster berechnet. Wählen Sie diejenige mit der geringsten Streuung.

aria_ave.jpg.png

python


def vari(data):
    count = len(data)
    av = sum(data)/count
    void = []
    total = 0
    for d in data:
        diff = (d - av)**2
        total += diff
    pvariance = total/count

    return pvariance


def selective_ave(image):
    av_image = np.zeros(image.shape)
    
    for i in range(2, image.shape[0] - 2):
        for j in range(2, image.shape[1] - 2):

            center_neighbour = [image[i+1, j-1],image[i+1, j],image[i+1, j+1],image[i, j-1],
                image[i, j+1],image[i-1, j-1],image[i-1, j],image[i-1, j+1]]

            l_u_neighbour = [image[i-2, j-2],image[i-2, j-1],image[i-1, j-2],image[i-1, j-1],
                image[i-1, j],image[i, j-1],image[i, j]]
            
            up_neighbour = [image[i-2, j-1],image[i-2, j],image[i-2, j+1],
                image[i-1, j-1],image[i-1, j],image[i-1, j+1],image[i, j]]

            r_u_neighbour = [image[i+2, j+2],image[i+2, j+1],image[i+1, j+2],image[i+1, j+1],
                image[i+1, j],image[i, j+1],image[i, j]]

            right_neighbour = [image[i-1, j+2],image[i, j+2],image[i+1, j+2],
                image[i-1, j+1],image[i, j+1],image[i+1, j+1],image[i, j]]
            
            left_neighbour = [image[i-1, j-2],image[i, j-2],image[i+1, j-2],
                image[i-1, j-1],image[i, j-1],image[i+1, j-1],image[i, j]]

            l_d_neighbour = [image[i+2, j-2],image[i+2, j-1],image[i+1, j-2],
                image[i+1, j-1],image[i+1, j],image[i, j-1],image[i, j]]

            down_neighbour = [image[i+2, j-1],image[i+2, j],image[i+2, j+1],
                image[i+1, j-1],image[i+1, j],image[i+1, j+1],image[i, j]]

            r_d_neighbour = [image[i+2, j+2],image[i+2, j+1],image[i+1, j+2],
                image[i+1, j+1],image[i+1, j],image[i, j+1],image[i, j]]
            
    
            nb_list = [center_neighbour, l_u_neighbour, up_neighbour,
                r_u_neighbour, right_neighbour, left_neighbour,
                l_d_neighbour, down_neighbour, r_d_neighbour]

            number = 0
            vari_max = 0

            for nb in nb_list:
                pre_vari = vari(nb)
                
                if vari_max < pre_vari:
                    vari_max = pre_vari
                    max_index = number
                
                number += 1
            
            result = statistics.mean(nb_list[max_index])

            av_image[i, j] = result
 
    return av_image

select_av =  selective_ave(res)
cv2.imwrite('20_select_av.jpg', select_av)

20_select_av.jpg

* Bilateraler Filter (Filter mit zwei Gaußschen Verteilungen) *

Implementierung der Glättung mit einem Gaußschen Filter. Die Gewichte werden entsprechend der Entfernung zum interessierenden Punkt verteilt (je weiter die Entfernung, desto leichter). Bis zu diesem Punkt ist es dasselbe wie ein normaler Gauß-Filter. Hier wird ferner die Gewichtung der Gaußschen Verteilung für die Differenz des Pixelwerts zwischen den Pixeln übernommen. Das heißt, (je größer die Differenz ist (je weiter der Pixelwert entfernt ist), desto geringer ist das zu glättende Gewicht, sodass der Kantenabschnitt (je größer die Differenz des Pixelwerts ist) weniger wahrscheinlich geglättet wird. Dadurch bleiben die Kanten erhalten.

python


bi = cv2.bilateralFilter(res,15, 20, 20)
cv2.imwrite('21_bilateral_fil.jpg', bi)

21_bilateral_fil.jpg

* Nicht lokaler Mittelwertfilter *

Während der bilaterale Filter die Differenz der Pixelwerte gewichtet Hier wird der Unterschied in der Ähnlichkeit mit anderen kleinen Bereichen (umgebenden Bildbereichen) gewichtet. Mit anderen Worten, wenn sich in der Peripherie viele ähnliche Bilder befinden, ist die Glättung stark, und wenn sie nicht ähnlich sind, ist die Glättung leicht.

python


dst = cv2.fastNlMeansDenoising(res, None, 10, 7, 21)
cv2.imwrite('22_non_l_m_fil.jpg', dst)

22_non_l_m_fil.jpg

* Medianfilter *

Zum Zeitpunkt der Filterung wird der Medianwert des interessierenden Bereichs ausgegeben. Der Medianwert ist (M × N + 1) / 2, gerechnet ab dem Pixel mit dem kleinsten Pixelwert für ein Bild von M × N Pixeln. Der Wert des zweiten Pixels. Dieser Filter ist wirksam bei spitzenartigen Geräuschen, wie z. B. mit Sesam bestreut.

python


median = cv2.medianBlur(noicy_image, 3)
cv2.imwrite('24_median_fil.jpg', median)

Vor 23_spike_noise.jpg

Nach dem Verkauf 24_median_fil.jpg

Referenzierte Site http://optie.hatenablog.com/entry/2018/03/21/185647 https://theailearner.com/2019/05/25/laplacian-of-gaussian-log/ https://algorithm.joho.info/programming/python/opencv-canny-edge-detecte-py/

das ist alles

Recommended Posts

Digitale Bildverarbeitung (räumliche Filterung)
Lesen Sie die digitale Bildverarbeitung
[Bildverarbeitung] Posterisierung
Bildverarbeitung 100 Schläge ①
Bildverarbeitung mit MyHDL
Erste Python-Bildverarbeitung
Bildverarbeitung mit Python
Bildverarbeitung mit PIL
Bildverarbeitung mit Python (Teil 2)
opencv-python Einführung in die Bildverarbeitung
Bildverarbeitung mit PIL (Pillow)
100 Schläge bei der Bildverarbeitung !! (011-020) Frühes Spiel
100 Klopfen bei der Bildverarbeitung !! (001 - 010) Vorsichtig und vorsichtig
Bildverarbeitung mit Python (Teil 1)
Bildverarbeitung mit Python (3)
Bildverarbeitung mit Python (Pillow)
Bildverarbeitungssammlung in Python
Bildausdehnung und Kontraktionsverarbeitung
[Python] Bildverarbeitung mit Scicit-Image
Grundlagen der Echtzeit-Bildverarbeitung mit opencv
[Python] Verwenden von OpenCV mit Python (Bildfilterung)
Persönliche Notizen für die Python-Bildverarbeitung
Die Bildverarbeitung mit Python 100 klopft an die Binärisierung Nr. 3
Bildverarbeitung 100 Klopfen Q9, Q10 (Filter) Beschleunigung
Umweltfreundliches Scraping mit Bildverarbeitung
100 Bildverarbeitung mit Python Knock # 2 Graustufen
Bildverarbeitung | Vorhersage von Arten aus Bildern