[PYTHON] Traitement de détection de sommets unidimensionnel et bidimensionnel

Détection de sommets unidimensionnelle

Lorsque le processus de convolution est effectué avec [-1, 1], la partie montante devient une valeur dépassant 0 et la partie descendante devient inférieure à 0. En utilisant cela, un drapeau ascendant et un drapeau descendant sont créés. Le point où les drapeaux se chevauchent est le sommet.

import math
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import PIL.Image
import random
import scipy.ndimage

#Détection de sommets unidimensionnelle
x = np.array([0, 0, 1, 0, 0])
print("x", x, "Tableau cible")
conv1 = np.convolve(x, [1, -1], mode="full")
print("conv1", conv1, "[-1, 1]Marquez les points ascendants et descendants avec le filtre de")
flag1 = (conv1 > 0).astype(int)
print("flag1", flag1, "Drapeau du point montant")
flag2 = (conv1 <= 0).astype(int)
print("flag2", flag2, "Drapeau du point de descente")
flag1 = flag1[:-1]
print("flag1", flag1, "Coupez une extrémité du drapeau montant pour correspondre à la longueur")
flag2 = flag2[1:]
print("flag2", flag2, "Coupez le début du drapeau descendant par un et alignez-le avec le sommet et alignez la longueur.")
flag3 = flag1 & flag2
print("flag3", flag3, "Le résultat de la mise en ET du drapeau croissant et du drapeau décroissant est le point de crête.")

Résultat d'exécution

x [0 0 1 0 0]Tableau cible
conv1 [ 0  0  1 -1  0  0] [-1, 1]Marquez les points ascendants et descendants avec le filtre de
flag1 [0 0 1 0 0 0]Drapeau du point montant
flag2 [1 1 0 1 1 1]Drapeau du point de descente
flag1 [0 0 1 0 0]Coupez une extrémité du drapeau montant pour correspondre à la longueur
flag2 [1 0 1 1 1]Coupez le début du drapeau descendant par un et alignez-le avec le sommet et alignez la longueur.
flag3 [0 0 1 0 0]Le résultat de la mise en ET du drapeau croissant et du drapeau décroissant est le point de crête.

Créer un échantillon

cycle = 4
data = np.zeros(100)
cycleWidth = len(data) / cycle
unit = math.pi / cycleWidth * 2
for i in range(cycle):
    for j in range(int(cycleWidth)):
        data[i * int(cycleWidth) + j] = math.cos(unit * float(j))

plt.plot(data)
plt.show()

一次元サンプル.PNG

Effectuer la détection de sommets sur un échantillon

#Fonctionne la détection de sommets unidimensionnelle
def detectPeak1D(x):
    conv1 = np.convolve(x, [1, -1], mode="full")
    flag1 = (conv1 > 0).astype(int)
    flag2 = (conv1 <= 0).astype(int)
    flag1 = flag1[:-1]
    flag2 = flag2[1:]
    flag3 = flag1 & flag2
    return flag3

peaks = detectPeak1D(data)
plt.plot(data)
plt.plot(peaks)
plt.show()

一次元サンプル2.PNG

La montée est détectée comme un pic pour les points horizontaux

data[data > 0.7] = 0.7
peaks = detectPeak1D(data)
print("Si les sommets sont horizontaux, la montée est détectée comme les sommets")
plt.plot(data)
plt.plot(peaks)
plt.show()

一次元サンプル3.PNG

Détection de sommets bidimensionnelle

Les données bidimensionnelles sont le résultat de la mise en ET des "fanions exécutés pour toutes les lignes (tableau bidimensionnel)" et des "fanions exécutés pour toutes les colonnes (tableau bidimensionnel)" pour la détection de vertex unidimensionnelle. Être au sommet de

#Détection de sommets bidimensionnelle
x = np.array([
    [0, 0, 1, 0, 0],
    [0, 2, 3, 2, 0],
    [1, 3, 5, 3, 1],
    [0, 2, 3, 2, 0],
    [0, 0, 1, 0, 0],
])
print(x, "Données cibles")
#Effectuer une détection de sommet sur toutes les lignes
peaks1 = []
for ix in x:
    peak = detectPeak1D(ix)
    peaks1.append(peak)
peaks1 = np.array(peaks1)
print(peaks1, "Indicateur de détection de sommet horizontal")
#Effectuer une détection de sommet sur toutes les colonnes
peaks2 = []
for ix in x.transpose():
    peak = detectPeak1D(ix)
    peaks2.append(peak)
peaks2 = np.array(peaks2).transpose() #Exécuter la détection par transposition et revenir à l'original
print(peaks2, "Indicateur de détection de sommet vertical")
peaks3 = (peaks1 & peaks2).astype(int)
print(peaks3, "ET les indicateurs de détection de ligne et de colonne et les indicateurs restants deviennent les indicateurs de sommet à deux dimensions.")

Résultat d'exécution

[[0 0 1 0 0]
 [0 2 3 2 0]
 [1 3 5 3 1]
 [0 2 3 2 0]
 [0 0 1 0 0]]Données cibles
[[0 0 1 0 0]
 [0 0 1 0 0]
 [0 0 1 0 0]
 [0 0 1 0 0]
 [0 0 1 0 0]]Indicateur de détection de sommet horizontal
[[0 0 0 0 0]
 [0 0 0 0 0]
 [1 1 1 1 1]
 [0 0 0 0 0]
 [0 0 0 0 0]]Indicateur de détection de sommet vertical
[[0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 1 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]]ET les indicateurs de détection de ligne et de colonne et les indicateurs restants deviennent les indicateurs de sommet à deux dimensions.
#Fonctionne la détection de sommets bidimensionnelle
def detectPeak2D(x):
    peaks1 = []
    for ix in x:
        peak = detectPeak1D(ix)
        peaks1.append(peak)
    peaks1 = np.array(peaks1)
    peaks2 = []
    for ix in x.transpose():
        peak = detectPeak1D(ix)
        peaks2.append(peak)
    peaks2 = np.array(peaks2).transpose()
    flag = (peaks1 & peaks2).astype(int)
    return flag

Création d'un échantillon de données bidimensionnel

#Créez des données de test pour la détection de sommets bidimensionnels, faites pivoter les données avec des sommets unidimensionnels
random.seed(1)
data2d = np.zeros((200, 200))
pattern = np.array([1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1])
for i in range(10):
    ox, oy = random.randrange(200), random.randrange(200)
    for j in range(50):
        rad = (math.pi / 50) * j
        for ix, v in enumerate(pattern):
            pos = ix - len(pattern) / 2
            x = ox + math.cos(rad) * pos
            y = oy + math.sin(rad) * pos
            if x < 0: continue
            if x >= 200: continue
            if y < 0: continue
            if y >= 200: continue
            data2d[int(x)][int(y)] = v

plt.figure(figsize=(10,4),dpi=200)
plt.imshow(data2d)
plt.show()

Exemple d'image bidimensionnelle

二次元データサンプル1.PNG

Effectuer une détection de sommets bidimensionnelle

peaks = detectPeak2D(data2d)
print("Puisque tous les fronts montants sont reconnus comme des sommets, les points où la même valeur est continue sont reconnus comme des sommets.")
plt.figure(figsize=(10,4),dpi=200)
plt.imshow(peaks)
plt.show()

二次元データサンプル2.PNG

Exécution de la détection de sommets bidimensionnelle après lissage

data2dGaussian = scipy.ndimage.gaussian_filter(data2d, sigma=1)
peaks = detectPeak2D(data2dGaussian)
print("Les sommets peuvent être détectés normalement en lissant et en éliminant autant que possible les parties parallèles.")
plt.figure(figsize=(10,4),dpi=200)
plt.imshow(peaks)
plt.show()

二次元データサンプル3.PNG

Attention etc.

Il n'y a pas de prétraitement ou de traitement, et c'est un processus qui suppose des données qui ont une belle forme de montagne. Fondamentalement, je pense que cela ne fonctionne souvent pas comme prévu à moins d'être lissés, alors utilisez-les tels quels Peu importe qu'il s'agisse d'une moyenne mobile ou d'un filtre gaussien, utilisez-le après l'avoir lissé.

c'est tout.

Recommended Posts

Traitement de détection de sommets unidimensionnel et bidimensionnel
100 coups sur le traitement d'image !! (001 --010) Soigneusement et soigneusement
Traitement de l'expansion et de la contraction de l'image
[Traitement d'image] Poo-san est nu par détection de bord en utilisant Python et OpenCV!