[Chapitre 5 (Convolution pour toute la famille !) Introduction à la convolution OpenCv, bruit + flou d'image, détection de contours, opérations morphologiques (compréhension populaire et contact avec les opérations liées à la convolution d'image !)]

Chapitre 5 (Convolution pour toute la famille !) Introduction à la convolution OpenCv, bruit + flou d'image, détection de contours, opérations morphologiques (compréhension populaire et contact avec les opérations liées à la convolution d'image !) - Mise à jour

1. Introduction

1.1 Introduction à la convolution

(1)卷积核:Qu'il s'agisse de la couche convolutive de CNN dans le réseau neuronal , de l'opération de filtrage dans OpenCv ou du traitement morphologique d'images binaires (le multicanal est également possible mais pas couramment utilisé), les connaissances liées à la convolution sont utilisées et la convolution est utilisée Le noyau effectue une opération de glissement sur l'image. (Les convolutions dans les réseaux de neurones sont similaires mais pas identiques aux convolutions dans le filtrage ).

(2)CNN中的卷积:La convolution est couramment utilisée dans le traitement d'images, la vision par ordinateur, la reconnaissance vocale, le traitement du langage naturel, la classification de texte, la reconnaissance de formes et d'autres domaines. Dans le domaine de l'image , il peut extraire des caractéristiques des images et les utiliser pour mieux comprendre le contenu de l'image. La convolution est généralement utilisée pour détecter les bords , les textures , les objets et autres caractéristiques des images . Il extrait les caractéristiques de l'image en faisant glisser un petit filtre (appelé noyau de convolution) et combine les caractéristiques extraites pour obtenir de meilleurs résultats d'analyse d'image.

(3)滤波中的卷积核:Le filtrage d'image est une technique permettant d'améliorer la qualité de l'image en supprimant le bruit , le flou ou d'autres caractéristiques indésirables d'une image . Il peut également être utilisé pour augmenter le contraste d'une image ou pour mettre en évidence les bords ou les caractéristiques d'une image .

(4)形态学操作的卷积:Une fois l'image prétraitée -> segmentation de l'arrière-plan et de la cible, divers points de bruit, trous et légères connexions apparaissent souvent, c'est pourquoi des opérations morphologiques sont souvent utilisées (similaires au traitement secondaire des produits). Parmi eux, le noyau de convolution ( élément structurel ) peut être défini indépendamment dans les opérations morphologiques, et est divisé en rectangle, croix, ellipse (une méthode de définition d'élément structurel basée sur la fonction de dessin sera partagée plus tard dans le chapitre sur les opérations morphologiques ) ; principales opérations morphologiques Dont érosion, dilatation, opération d'ouverture, opération de fermeture, chapeau haut de forme, chapeau noir, gradient morphologique . Être familier avec les connaissances théoriques pertinentes en matière de morphologie nous aidera à effectuer un traitement secondaire des images, à obtenir le contour cible souhaité et à sélectionner les cadres d'objets.

(5)导语:Par conséquent, avant d’apprendre l’apprentissage profond, le flou d’image, l’extraction des bords de l’image et les opérations morphologiques, il est nécessaire d’acquérir les connaissances de base de la convolution.

1.2 Fonctionnement flou

(1)作用:L'opération de flou est l'opération de base la plus couramment utilisée dans le prétraitement d'image, qui peut réduire le bruit , améliorer la qualité de l'image et réduire la complexité des algorithmes ultérieurs.

(2)分类:Le flou de l'image est divisé en flou moyen, médian, bilatéral, gaussien et flou .

(3)导语:Comment utiliser ces opérations de flou de manière flexible, il est donc nécessaire de comprendre les principes sous-jacents des différents flous et d'être capable de sélectionner les opérations de flou appropriées pour prétraiter l'image en fonction des différentes caractéristiques de l'image.

1.3 Détection des contours

(1)作用:Peut être utilisé pour extraire des limites, des contours et des textures.

(2)分类: La classification de la segmentation d'image est mentionnée au chapitre 3. La segmentation par seuil appartient à la première catégorie de segmentation d'arrière-plan et de cible, et la détection de contours est la deuxième catégorie de segmentation. La détection des contours peut être divisée en : basée sur des opérateurs différentiels , des opérateurs de gradient et la détection des contours Canny avec le meilleur effet.

(3)导语:La détection des contours est également couramment utilisée dans des cas tels que la détection de lignes de voie et la transformation de perspective dans la correction de documents. Par conséquent, il est nécessaire de comprendre les algorithmes de détection des contours et d’être capable de sélectionner de manière flexible les algorithmes de segmentation d’arrière-plan et de cible en fonction de différents scénarios.

1.4 Opérations morphologiques

(1)作用:Les opérations morphologiques jouent un rôle très important dans le traitement de l'image. Son principe est basé sur la forme du modèle (la forme du noyau de convolution). Il peut utiliser la corrosion, l'expansion, les opérations d'ouverture, les opérations de fermeture et d'autres opérations pour extraire les caractéristiques de l'image. .ou dans le but de segmenter l'image.
(2)分类:Corrosion (缩小目标), expansion (扩大目标), opération d'ouverture (先腐蚀再膨胀), opération de fermeture (先膨胀再腐蚀), opération chapeau haut de forme (噪声=原图-开运算(先腐后膨)), opération chapeau noir (空洞=闭运算(先膨后腐)-原图), gradient morphologique (物体边缘=原图-腐蚀), diverses opérations mixtes d'expansion et d'érosion selon les besoins réels, etc.

(3)导语:Lorsque nous segmentons l'arrière-plan et la cible, il y aura des trous, du bruit ou des connexions d'objets. Il est donc nécessaire d’effectuer un débruitage morphologique, de combler des trous ou de segmenter des objets. Il est donc nécessaire de se familiariser avec les opérations morphologiques.

2. Introduction à la convolution

2.1 Opération de convolution

(1)卷积:

  • Le noyau de la fenêtre du noyau de convolution glissant glisse sur l' image d'entrée Img, les zones qui se chevauchent sont multipliées et finalement ajoutées, d'abord horizontalement , puis verticalement , et le résultat de sortie est ce que nous appelons une carte de caractéristiques. Parce que la convolution consiste à extraire des fonctionnalités.

  • Ici, la taille (Img) est de 5x5 et la taille (Kernel) est de 3x3. On peut voir sur la figure que les pixels non nuls forment le chiffre 1. Ici, un noyau de convolution couramment utilisé pour la netteté des images est sélectionné pour la démonstration.

  • Les noyaux de convolution sont généralement réglés sur des nombres impairs tels que : 1x1, 3x3, 5x5. Par rapport aux noyaux de convolution pairs, une certaine quantité de calcul peut être économisée dans les calculs de convolution ; dans le filtrage, l'appariement du filtre peut être assuré ; à en même temps, un nombre impair de noyaux de convolution facilite la recherche du point central et facilite le positionnement. S'il y a un nombre pair, un flou de positionnement se produira.

Figure 2.1.1 Image d'entrée, noyau de convolution

(2)卷积过程:

   Comme le montre la figure ci-dessous, les paramètres de convolution sont : la foulée est de 1 et le rembourrage est de 0. À ce stade, vous pouvez remarquer que l’image d’entrée est de 5x5 et que la carte des caractéristiques de sortie a une taille de 3x3. Lorsque le nombre de couches convolutives d'un réseau d'apprentissage profond est très grand, la sortie de la carte des caractéristiques après chaque convolution sera réduite et sera finalement réduite à une taille de 1x1. Par conséquent, les calculs de convolution ultérieurs ne peuvent pas être effectués. Une opération de remplissage est donc nécessaire .

Figure 2.1.2 Processus de convolution

2.2 Remplissage (extension de la taille de la carte des entités en sortie)

(1)参数: 输入:5x5; 卷积核:3x3; 步幅:2; 填充:1(上下左右各填充1行/列);输出:5x5。

(2)特点:Selon la carte des caractéristiques de sortie par rapport à la carte des caractéristiques d'entrée, la valeur du pixel qui compose le nombre 1 est évidemment plus grande , et les autres valeurs de pixels qui y sont connectées sont évidemment plus petites , et plus la différence entre les deux est grande . Il s'agit du noyau de convolution qui sélectionne le noyau de filtre de netteté couramment utilisé , sum (convolution kernel) = 1 (>1则为亮度增强,<1降低亮度), que vous verrez dans la netteté du flou ultérieure.

(3)注意点:Tout en expliquant l'opération de convolution, à travers cet exemple, il est expliqué que l'image est composée de valeurs de pixels. Plus la valeur du pixel est grande, plus la luminosité est élevée ; plus la différence entre la valeur du pixel de contour et les pixels adjacents est grande, plus le contraste est fort. , qui appartient également à la netteté de l'image. ;


Figure 2.2.1 Processus de convolution (foulée=1, rembourrage=1)

  • Étant donné que la gamme globale de captures d’écran est large, une capture d’écran par ligne ci-dessous est pour le confort de tous.


Figure 2.2.2 Schéma de fonctionnement de convolution

2.3 Stride (peut réduire la taille de la carte des caractéristiques de sortie et réduire la quantité de calcul pour la prochaine convolution)

(1)步幅:Le noyau de convolution se déplace à un rythme. Si la foulée n'est pas 1, en supposant qu'elle soit 2 ( 每次滑动两个单元), la taille de la carte des caractéristiques d'entrée de cet exemple deviendra 3x3.


Figure 2.3.3 Processus de convolution (foulée=2, rembourrage=1)

(2)总结:Lorsque le remplissage > 1, la taille de la carte des caractéristiques de sortie est augmentée pour conserver la même taille que l'image d'origine ; lorsque la foulée > 1, la taille de la carte des caractéristiques de sortie est réduite pour réduire la quantité de calculs de convolution ultérieurs.

2.4 Formule de calcul

* OH = IH + 2 P − FHS + 1 ( 1 ) OH = \frac{IH+2P-FH}{S}+1 \qquad (1)(1)备注: 输入大小(IH,IW);滤波器大小(FH.FW);输出大小(OH,OW);填充P,步幅S。
OH _=SJe H+2P _FH _+1( 1 )
OW = IW + 2 P − FWS + 1 ( 2 ) OW = \frac{IW+2P-FW}{S}+1 \qquad (2)O W=SJe W+2P _FW _+1( 2 )

2.5 Code de vérification (implémenté par Pytorch)

(1)代码:

import torch
import torch.nn.functional  as F
# 输入
input =torch.tensor([[0,0,1,0,0],
                    [0,2,3,0,0],
                    [0,0,4,0,0],
                    [0,0,5,0,0],
                    [0,6,7,8,0]])
# 卷积核
kernel = torch.tensor([[0,-1,0],
                      [-1,5,-1],
                      [0,-1,0]])

# nn卷积操作,数据格式是(batch_size,channel,h,w)
input = torch.reshape(input,(1,1,5,5))
kernel = torch.reshape(kernel,(1,1,3,3))
print(input)
print(kernel)

# 进行卷积操作,input:输入图像;kernel:卷积核;stride:步伐;,padding:填充,默认填充数据为0
output = F.conv2d(input,kernel,stride=2,padding=1)
print(output)

(2)卷积结果:La convolution est une opération mathématique et peut être implémentée dans n'importe quel langage ou bibliothèque Python que nous utilisons. Cependant, l'implémentation la plus complète actuellement est le framework pytorch, qui est la tendance générale.

tensor([[[[0, 0, 1, 0, 0],
          [0, 2, 3, 0, 0],
          [0, 0, 4, 0, 0],
          [0, 0, 5, 0, 0],
          [0, 6, 7, 8, 0]]]])
tensor([[[[ 0, -1,  0],
          [-1,  5, -1],
          [ 0, -1,  0]]]])
tensor([[[[ 0,  2,  0],
          [ 0, 12,  0],
          [-6, 16, -8]]]])

2.6 Liens de lecture recommandés

初衷:
1) Mettez des liens recommandés. D'une part, une partie du contenu de cet article renvoie à des liens pertinents ;
2) En même temps, j'ai l'impression que ces articles sont plutôt bien écrits et ont déjà une très bonne roue. Il n'y a pas il faut réinventer la même roue ;
3) Chacun basé sur Pour comprendre le niveau, choisissez de lire, comprendre, puis synthétiser en fonction de plusieurs articles, afin d'avoir une compréhension approfondie d'un point (个人觉得有很多文章,都有自己的定位以及亮点,很难单读一篇文章就全对该知识点理解得很透彻,但是看多了相关文章,学习每一篇文章的亮点之后,便会有自己的独特见解).
4) Il est pratique pour tout le monde de trouver des articles de haute qualité liés à ce point de connaissance et d'améliorer l'efficacité.

1. Petit monticule, explication de la convolution, facile à comprendre
2. L'explication la plus simple à comprendre de la convolution
Remarque : La convolution dans le système de traitement du signal est fondamentalement la même que la convolution dans OpenCV , mais elles présentent encore quelques différences. Les convolutions dans les systèmes de traitement du signal sont conçues pour manipuler les signaux, tandis que les convolutions d'OpenCV sont utilisées pour le traitement des images. De plus, l'opération de convolution d'OpenCV fournit des paramètres plus ajustables, tels que la taille du noyau, la foulée, etc., tandis que la convolution dans les systèmes de traitement du signal est plus simple, avec un seul paramètre, la forme du signal
. la méthode d'accumulation


2. Image floue

导语:L'opération de flou débruite principalement l'image . Par conséquent, avant d'apprendre l'opération de flou, il est nécessaire de comprendre les types de bruit . En combinaison avec les caractéristiques de plusieurs traitements de flou, vous pouvez choisir l'algorithme de flou approprié en fonction des caractéristiques de l'image pour flouter la qualité de l'image et réduire la complexité du traitement de l'image.

2.1 Introduction au bruit courant

2.1.1 Bruit de sel et de poivre

(1)椒盐噪声:Taches de sel et de poivre dans l'image, qui sont des valeurs de pixels maximales (blanches) ou minimales (noires), leur existence affectera la qualité de l'image ;

(2)记忆方法:Poivre noir ( noir ), sel ( blanc ), lorsque l'image comporte des points noirs et blancs, un filtrage médian peut être utilisé pour supprimer le bruit. En même temps, vous pouvez le simuler en ajoutant aléatoirement du bruit clair et sombre à l'image. Parmi eux, les vieux téléviseurs noir et blanc des années 1990 sont dotés d’écrans en forme de flocon de neige qui sont en réalité des bruits poivre et sel. Le bruit de couleur qui apparaît sur les téléviseurs couleur est un bruit gaussien.


Figure 2.1.1.1 Écran de flocon de neige (bruit de sel et de poivre)

(3)代码:(Ajouter du bruit de sel et de poivre aux images)

# 作者:OpenCv机器视觉
# 时间:2023/1/21
# 功能:给图片添加椒盐噪声
import cv2 as cv
import numpy as np



# 添加椒盐噪声
def make_salt_pepper_noise(img):
    # 进行添加噪声
    for i in range(1000):
        # 椒(黑色)噪点,随机坐标
        xb = np.random.randint(0, w)
        yb = np.random.randint(0, h)
        # 盐(白色)噪点,随机坐标
        xw = np.random.randint(0, w)
        yw = np.random.randint(0, h)

        # 根据坐标进行添加早点
        img[yb, xb, :] = 255  # h,w,c,第一个参数是高度、第二个参数是宽度、第三个参数是通道数
        img[yw, xw, :] = 0  # h,w,c,第一个参数是高度、第二个参数是宽度、第三个参数是通道数

    return img

# 读取图片
img = cv.imread(".\\img\\lena.jpg")

# 获取图片,h,w,c参数
h,w,c=img.shape
# 添加椒盐噪声
img_msp = make_salt_pepper_noise(img.copy())
# 图像拼接
stack = np.hstack([img, img_msp])


# 显示图像
cv.namedWindow("img", 0)
cv.imshow("img", stack)
cv.waitKey(0)


(4)效果:On peut voir que la différence de pixels entre le bruit sel et poivre est grande, le bruit est plus évident et le contraste entre les points clairs et sombres est fort, ce qui le rend plus éblouissant.

Figure 2.1.1.2 Image originale (à gauche), bruit de sel et de poivre (à droite)


2.1.2 Bruit aléatoire

(1)随机噪声: Également appelé bruit de fond, il n'a pas de régularité et affectera le contraste et la luminosité de l'image. Le filtrage moyen a le meilleur effet. 椒盐噪声,黑白点;高斯噪声彩色点,但是符合高斯分布;随机噪声个人理解,就是彩色噪声,同时不符合规律分布的就是随机噪声。(Vous pouvez vous référer à l'article 1. Ma compréhension personnelle n'est pas assez complète. Étant donné que le bruit aléatoire est très similaire au bruit du sel et du poivre, je le comprendrai à la manière du bruit du sel et du poivre. Cependant, le bruit aléatoire n'a pas de règles de distribution. (Si vous avez une bonne compréhension de la méthode, veuillez commenter dans la zone de commentaires. Discutons-en ensemble.)

(2)代码:

# 作者:OpenCv机器视觉
# 时间:2023/1/24
# 功能:给图片添加随机噪声
import cv2 as cv
import numpy as np

# 生成随机噪声
def make_random_noise(img_noise, num=100):

    # 获取图片h,w,c参数
    h,w,c = img_noise.shape

    # 加噪声
    for i in range(num):
        b = np.random.randint(0,255)    # 每个通道数值随机生成
        g = np.random.randint(0,255)
        r = np.random.randint(0,255)

        x = np.random.randint(0, w)  # 随机生成指定范围的整数
        y = np.random.randint(0, h)
        img_noise[y, x] = (b,g,r)   # opencv读取图像后,是BGR格式

    return img_noise



img = cv.imread(".\\img\\lena.jpg")


# 生成随机噪声,噪声点数量没加,就按照函数默认参数100来
img_rn = make_random_noise(img.copy(),5000)
# 合并图像
stack = np.hstack([img,img_rn])

# 显示图像
cv.namedWindow("img", 0)
cv.imshow("img", stack)
cv.waitKey(0)

(3)效果:La répartition du bruit est irrégulière , couleur (image couleur)/noir et blanc (image en niveaux de gris), un peu comme la répartition du bruit poivre et sel (noir et blanc), car généré aléatoirement ; c'est aussi un peu comme le bruit gaussien (couleur), mais il n'y a pas de règle de distribution. Il suffit de savoir à peu près de quoi il s’agit, et il n’est pas nécessaire de le forcer pour s’en souvenir, c’est juste un bruit irrégulier de toute façon.


Figure 2.1.2.1 Image originale (à gauche) bruit aléatoire (à droite)

2.1.3 Bruit gaussien

(1)高斯噪声:Le bruit gaussien fait référence à un bruit aléatoire dans une image, qui dégrade la qualité de l'image. Les téléviseurs couleur à l'ancienne ont tendance à avoir beaucoup de bruit coloré les jours de pluie , qui est du bruit gaussien (les images en niveaux de gris ont également du bruit gaussien, mais ce n'est que du bruit gris).


Figure 2.1.3.1 Bruit de télévision couleur (bruit gaussien)

(2)代码(Ajout de bruit gaussien aux images en couleur) :

# 作者:OpenCv机器视觉
# 时间:2023/1/21
# 功能:给彩色图片添加高斯噪声

import numpy as np
import cv2 as cv



def make_gauss_noise(img, mean=0, sigma=25):
    img = np.array(img / 255, dtype=float)  # 将原始图像的像素值进行归一化,因为高斯分布是在0-1区间
    # 创建一个均值为mean,方差为sigma,呈高斯分布的图像矩阵
    noise = np.random.normal(mean, sigma / 255.0, img.shape)
    add = img + noise  # 将噪声和原始图像进行相加得到加噪后的图像
    img_mgn= np.clip(add, 0.0, 1.0)
    img_mgn = np.uint8(img_mgn * 255.0)

    return img_mgn

img = cv.imread(".\\img\\lena.jpg")
img_mgn = make_gauss_noise(img,0,np.random.randint(25,50))

# 图像拼接
stack = np.hstack([img, img_mgn])


# 显示图像
cv.namedWindow("img", 0)
cv.imshow("img", stack)
cv.waitKey(0)

(3)添加效果:

Figure 2.1.3.2 Image originale (à gauche), bruit gaussien ajouté (à droite)

2.1.3 Articles de lecture recommandés

1. Traitement numérique de l'image : modèles de bruit (bruit sel et poivre, bruit aléatoire, bruit gaussien) et méthodes de filtrage
2. Flou de l'image (filtrage moyen, gaussien, médian, bilatéral)
3. Flou de mouvement de l'image
4. Image plus bruit gaussien


2.2 Flou de mouvement

(1)运动模糊:Cela est dû au fait que la vitesse de mouvement relative de la caméra ou de la cible de détection est trop rapide (le flou de mouvement est souvent flou dans une direction ) ; par conséquent, lors de la sélection d'une caméra, nous devons souvent prendre en compte la vitesse de mouvement et la fréquence d'images de l'objet. Si la vitesse de déplacement est rapide et que la fréquence d'images est faible, il est facile de provoquer un flou de mouvement. La solution au flou de mouvement consiste à utiliser un appareil photo avec une fréquence d’images plus élevée.

(2)代码:Ajoutez du flou de mouvement aux images.

# 作者:OpenCv机器视觉
# 时间:2023/1/21
# 功能:给图片添加运动模糊效果
import cv2 as cv
import numpy as np

# 制作运动模糊
def make_motion_blur_noise(img, degree=180*1, angle=90):
    
    # 这里生成任意角度的运动模糊kernel的矩阵, degree越大,模糊程度越高
    M = cv.getRotationMatrix2D((degree/2, degree/2), angle, 1)
    print(M)

    motion_blur_kernel = np.diag(np.ones(degree))
    print(motion_blur_kernel)

    motion_blur_kernel = cv.warpAffine(motion_blur_kernel, M, (degree, degree))
    print(motion_blur_kernel)

    motion_blur_kernel = motion_blur_kernel / degree
    print(motion_blur_kernel)

    blurred = cv.filter2D(img, -1, motion_blur_kernel)
    
    # convert to uint8
    cv.normalize(blurred, blurred, 0, 255, cv.NORM_MINMAX)
    blurred = np.array(blurred, dtype=np.uint8)
    return blurred

# 清晰原图
img = cv.imread(".\\img\\bxg_clear.jpg")
# 由于相机移动导致的运动模糊
img_original_motion_blur = cv.imread(".\\img\\bxg_original_motion_blur.jpg")

# 制作运动模糊
img_motion_blur = make_motion_blur_noise(img)
# 图像水平拼接,np.vstack为垂直拼接
stack = np.hstack([img,img_original_motion_blur,img_motion_blur])


# 显示图像
cv.namedWindow("img",0)
cv.imshow("img",stack)
cv.waitKey(0)

(3)运动模糊效果:Gauche : image originale claire ; milieu : flou de mouvement provoqué par le mouvement de la caméra ; droite : utilisation de code pour créer un effet de flou de mouvement.

Figure 2.1.3 Comparaison du flou de mouvement


2. 3 Flou moyen

(1)原理:Les valeurs de pixels autour de chaque pixel de l'image (couverture du noyau de filtre) sont additionnées et moyennées, puis cette moyenne est utilisée pour remplacer la valeur de pixel d'origine.

(2)类别:Il s'agit d'un filtrage linéaire (avec une relation linéaire, l'entrée et l'entrée sont obtenues par des opérations linéaires d' addition, de soustraction , de multiplication et de division de pixels . Le filtrage linéaire comprend également : le filtrage médian, le filtrage gaussien et le filtrage bilatéral. Les filtres non linéaires courants comprennent : le filtrage par dilatation et le filtrage par érosion dans les opérations morphologiques.
3)应用:Couramment utilisé pour supprimer le bruit aléatoire (application), car la plage de calcul est la plage couverte par le noyau de convolution, donc plus le noyau de convolution est grand , la valeur actuelle du pixel est la valeur moyenne de la plage de pixels environnante plus large, plus le calcul est grand. Plus l' image sera floue et déformée, plus le filtrage d'une image prendra de temps et certains détails seront flous. Parce qu'il est nécessaire de sélectionner la taille du noyau de filtre appropriée en fonction de la situation réelle.

(4)原理图解:La plupart des noyaux de filtre sont des nombres impairs. Ici, une matrice est générée avec 7x7la taille , et le noyau de filtre moyen est 3x3.

  • Noyau de convolution flou moyen :
    Noyau = 1 K w ∗ K h ( 1 1 ⋯ 1 1 1 ⋯ 1 ⋮ ⋮ ⋱ ⋮ 1 1 ⋯ 1 ) (3) Noyau = \frac 1{K_w*K_h} \begin{pmatrix } 1& 1 & \cdots &1 & \\ 1& 1 & \cdots &1 &\\ \vdots & \vdots & \ddots & \vdots \\ 1& 1&\cdots & 1 \end{pmatrix} \tag{3}Noyau _ _ _=Kw*Kh1 111111111 ( 3 )

  • Le noyau de convolution 3X3 est le suivant :

Figure 2.3.1 Noyau du filtre moyen 3x3

  • Processus de filtrage : multipliez et additionnez le noyau du filtre et les pixels couverts par l'image. Enfin, attribuez cette valeur au pixel rouge foncé. Lorsque le noyau de convolution traverse et fait glisser toute l'image, le filtrage est terminé.
Figure 2.3.2 Processus de filtrage

  • Résultat de l'opération du programme (le résultat est 58, marqué d'une marque)
均值滤波前:
[[255  10  10  10  10  10  10]
 [ 10  10  10 200  10  10  10]
 [ 10  10 200 200  10  10  10]
 [ 10 255  10 200  10  10  10]
 [ 10  10  10 200  10  10  10]
 [ 10  10 200 200 200  10  10]
 [ 10  10  10  10  10  10   0]]
均值滤波后:[[ 37  37  52  52  52  10  10]
 [ 375873  73  52  10  10]
 [ 64  58 122  94  73  10  10]
 [ 64  58 122  94  73  10  10]
 [ 64  58 122 116  94  31  10]
 [ 10  31  73  94  73  30   9]
 [ 10  52  94 137  94  51   9]]

5.疑问?:Étant donné que la valeur du pixel central du noyau de filtre est la valeur de pixel moyenne de la couverture du noyau de filtre, les noyaux de filtre de bord et des quatre coins s'étendront au-delà de l'image. Comment est-ce calculé ? (Comme indiqué ci-dessous)

Figure 2.3.3 Situation aux limites

  • Posez ensuite une question : (1) Si une partie du noyau de filtre dépasse l'image, alors la valeur du noyau de filtre est 1/9 ou 1/(le nombre de pixels chevauchant le noyau de filtre et l'image) [vérifié par les bords] ; ( 2) La valeur du coin supérieur gauche Cela a-t-il quelque chose à voir avec les pixels de la pièce jointe ? (3) Les pixels pertinents contribuent-ils dans la même mesure à la valeur du pixel dans le coin supérieur gauche ? Je l'ai donc personnellement vérifié grâce au code :

  • Après vérification, (1) : Aucun ; (2) (3) sont liés aux quatre pixels du coin supérieur gauche. Chaque pixel a une contribution différente, mais elle est symétrique (img[0][1] et img[1 ][0 ] L'un d'eux change la même valeur, et la valeur img[0][0] reste inchangée. img[1][1] change la même valeur, mais elle change). Les pixels sur le bord ou aux quatre coins sont en fait sous forme d'expansion, mais la valeur de remplissage et la méthode de calcul ne sont pas claires (peut-être en raison d'une compréhension personnelle limitée, ou cela peut être lié à la méthode de calcul de l'algorithme interne de l'API d'opencv). Tout le monde Comprenez simplement directement la valeur moyenne des pixels environnants. S'il s'agit d'un bord, remplissez-le simplement avec 0 pour le calcul auxiliaire. La comparaison des bords de l'image n'est pas notre objectif. Je viens de me poser cette question, j'ai donc trouvé des articles pertinents pour la vérifier. , mais en gros, cela n'a pas fonctionné. (Si vous êtes intéressé, vous pouvez ajuster la valeur matricielle dans le code à des fins de vérification et de test. S'il existe de bons articles ou quatre méthodes, vous pouvez en discuter dans la zone de commentaires. Nous mettrons à jour lorsque nous en saurons plus plus tard)

  • Code de vérification : (大家可以修改矩阵值,进行验证) voici pour créer une image (方便打印查阅图像值), la flouter et voir l'effet (也是进一步让大家了解图像其底层原理).

# 作者:OpenCv机器视觉
# 时间:2023/1/22
# 功能:利用numpy创建图片(从像素解释模糊),添加椒盐噪声+均值模糊

import cv2 as cv
import numpy as np

# 创建图片
def test():

    # 创建一个全为0,大小为7x7的单通道矩阵
    img = np.array([[255,10,10,10,10,10,10],
                    [10,10,10,200,10,10,10],
                    [10,10,200,200,10,10,10],
                    [10,255,10,200,10,10,10],
                    [10,10,10,200,10,10,10],
                    [10,10,200,200,200,10,10],
                    [10,10,10,10,10,10,0]
                    ],dtype=np.uint8)
    print("均值滤波前::")
    print(img)



    # 利用3x3的均值滤波核,对图像进行模糊
    blurred = cv.blur(img, (3, 3))
    print("均值滤波后::")
    print(blurred)

    cv.namedWindow("test", 0)
    cv.imshow("test", np.hstack([img,blurred]))
	cv.waitKey(0)


img = cv.imread(".\\img\\lena.jpg")

# 获取图片,h,w,c参数
h,w,c=img.shape
test()


  • Effet de vérification :
     Le code simule trois bruits poivre et sel (deux blancs et un noir). On constate qu'après filtrage moyen, l'image est débruitée, mais elle devient également floue. En même temps, les détails du numéro 1 ( l'effet de suppression du bruit du sel et du poivre n'est pas si idéal).
Figure 2.3.4 Créer des images et effet de filtrage moyen

(6)随机噪声+椒盐噪声+高斯噪声对比 and 不同滤波核大小对图像的模糊降噪模糊效果 and 均值滤波对随机噪声、椒盐噪声、高斯噪声的去噪效果

  • Code (部分代码会重复,主要是为了方便使用,直接全部复制,读取图片就可以看效果,不能自己过多操作):
# 作者:OpenCv机器视觉
# 时间:2023/1/25
# 功能:随机噪声+椒盐噪声+高斯噪声对比 and 不同滤波核大小对图像的模糊降噪模糊效果 and 均值滤波对随机噪声、椒盐噪声、高斯噪声的去噪效果

import cv2 as cv
import numpy as np


# 添加高斯噪声
def make_gauss_noise(image, mean=0, sigma=25):
    image = np.array(image / 255, dtype=float)  # 将原始图像的像素值进行归一化,因为高斯分布是在0-1区间
    # 创建一个均值为mean,方差为sigma,呈高斯分布的图像矩阵
    noise = np.random.normal(mean, sigma / 255.0, image.shape)
    add = image + noise  # 将噪声和原始图像进行相加得到加噪后的图像
    img_noise= np.clip(add, 0.0, 1.0)
    img_noise = np.uint8(img_noise * 255.0)


    return img_noise
# 添加随机噪声
def make_random_noise(img_noise, num=100):

    # 获取图片h,w,c参数
    h,w,c = img_noise.shape

    # 加噪声
    for i in range(num):
        b = np.random.randint(0,255)    # 每个通道数值随机生成
        g = np.random.randint(0,255)
        r = np.random.randint(0,255)

        x = np.random.randint(0, w)  # 随机生成指定范围的整数
        y = np.random.randint(0, h)
        img_noise[y, x] = (b,g,r)   # opencv读取图像后,是BGR格式


    return img_noise
# 添加椒盐噪声
def make_salt_pepper_noise(img_noise):
    # 进行添加噪声
    for i in range(1000):
        # 椒(黑色)噪点,随机坐标
        xb = np.random.randint(0, w)
        yb = np.random.randint(0, h)
        # 盐(白色)噪点,随机坐标
        xw = np.random.randint(0, w)
        yw = np.random.randint(0, h)

        # 根据坐标进行添加早点
        img_noise[yb, xb, :] = 255  # h,w,c,第一个参数是高度、第二个参数是宽度、第三个参数是通道数
        img_noise[yw, xw, :] = 0  # h,w,c,第一个参数是高度、第二个参数是宽度、第三个参数是通道数

    return img_noise



# 读取图片
img = cv.imread(".\\img\\lena.jpg")

# 获取图片,h,w,c参数
h,w,c=img.shape

# 添加随机噪声、椒盐噪声、高斯噪声
img_rn= make_random_noise(img.copy(),2000)
img_spn = make_salt_pepper_noise(img.copy())
img_gn = make_gauss_noise(img.copy())
img_noise_stack = np.hstack([img,img_rn,img_spn,img_gn])


# 不同大小的滤波核的滤波效果
blurred_3 = cv.blur(img_rn, (3, 3))
blurred_5 = cv.blur(img_rn, (5, 5)) # 对本张图片,5x5的滤波效果较好
blurred_7 = cv.blur(img_rn, (7, 7))
img_diffsize_stack = np.hstack([img,blurred_3,blurred_5,blurred_7])

# 对高斯噪声图进行中值模糊
blurred_rn5  = cv.blur(img_rn,(5,5))
blurred_spn5 = cv.blur(img_spn, (5, 5))
blurred_gn5 = cv.blur(img_gn, (5, 5))
img_diffnoise_stack = np.hstack([img,blurred_rn5,blurred_spn5,blurred_gn5])



# 垂直拼凑图片
stack = np.vstack([img_noise_stack,img_diffsize_stack,img_diffnoise_stack])    #

# 显示图像
cv.namedWindow("img", 0)
cv.imshow("img", stack)
cv.waitKey(0)
  • Effet:

1)噪声对比: Figure 1-4, montrant respectivement l'image originale, le bruit aléatoire, le bruit sel et poivre et le bruit gaussien.

2)滤波核大小影响:Comme le montre la figure 5-8, différents noyaux de convolution ont un meilleur effet de débruitage sur le bruit aléatoire, parmi lesquels 5x5 a un meilleur effet de débruitage. Plus le noyau de convolution est grand, meilleur est l'effet de suppression du bruit, les détails du contour de l'image sont flous et plus l'image est déformée.

3)均值滤波对不同噪声的抑制效果:La figure 9-12 montre la comparaison des effets de débruitage du filtre moyen sur différents bruits. On peut voir que le filtre moyen a un effet de suppression relativement bon sur le bruit aléatoire.
4)总结: La taille du noyau de convolution est généralement sélectionnée après avoir pesé le pour et le contre en fonction des besoins réels.

  • rendus
Figure 2.3.5 Effet de flou d'image

2.4 Flou médian

(1)原理:Le filtrage médian est une sorte de filtrage non linéaire.Son idée de base est de sélectionner une fenêtre sur l'image et de remplacer la valeur du pixel au centre de la fenêtre par la valeur médiane de toutes les valeurs de pixel de la fenêtre . Étant donné que le filtre médian utilise la médiane des valeurs de pixels dans la fenêtre plutôt que la moyenne des valeurs de pixels, il peut supprimer efficacement le bruit tout en conservant une résolution spatiale élevée.

(2)应用:Élimine efficacement le bruit du sel et du poivre.

(3)原理图解:

  • Une fois que le noyau du filtre a parcouru toute l’image, le débruitage est terminé.
Figure 2.4.1. Principe flou médian

Figure 2.4.2. Processus flou médian

(4)创建图片,查看中值滤波后变换:Effectuer un flou médian sur l'image créée (pratique pour imprimer et vérifier les valeurs de l'image)

  • code
# 作者:OpenCv机器视觉
# 时间:2023/1/25
# 功能:创建一张图片进行中值滤波,并查看前后的像素值

import cv2 as cv
import numpy as np

# 函数说明,ctrl点cv.medianBlur就可以进入,里面有说明函数如何使用以及参数含义
"""
    medianBlur(src, ksize[, dst]) -> dst
    .   The function smoothes an image using the median filter 
    .   @param src input 1-, 3-, or 4-channel image; when ksize is 3 or 5, the image depth should be
    .   CV_8U, CV_16U, or CV_32F, for larger aperture sizes, it can only be CV_8U.
    .   @param dst destination array of the same size and type as src.
    .   @param ksize aperture linear size; it must be odd and greater than 1, for example: 3, 5, 7 ...

    """

# 创建图片进行中模糊
def test():

    # 创建一个全为0,大小为7x7的单通道矩阵
    img = np.array([[255,10,10,10,10,10,10],
                    [10,10,10,200,10,10,10],
                    [10,10,200,200,10,10,10],
                    [10,255,10,200,10,10,10],
                    [10,10,10,200,10,10,10],
                    [10,10,200,200,200,10,10],
                    [10,10,10,10,10,10,0]
                    ],dtype=np.uint8)
    print("中值滤波前::")
    print(img)



    # 利用3x3的均值滤波核,对图像进行模糊
    blurred = cv.medianBlur(img, 3)
    print("中值滤波后::")
    print(blurred)

    cv.namedWindow("test", 0)
    cv.imshow("test", np.hstack([img,blurred]))



test()
cv.waitKey(0)
  • Résultats de sortie : valeurs de pixels avant et après filtrage : on peut voir que lors du filtrage médian des points de pixel de bord ou de diagonale, le remplissage n'est ni 0 ni 10. Le contenu d'expansion spécifique est déterminé par l'algorithme de filtrage médian opencv, donc il est la même chose que le filtrage moyen. Nous n'entrerons pas dans les détails ici. Le GIF précédent était rempli de 10. Vous pouvez comprendre le processus car les informations de bord ne sont pas si importantes et les informations importantes sont généralement affichées au centre de l'image.
均值滤波前:[[255  10  10  10  10  10  10]
 [ 10  10  10 200  10  10  10]
 [ 10  10 200 200  10  10  10]
 [ 10 255  10 200  10  10  10]
 [ 10  10  10 200  10  10  10]
 [ 10  10 200 200 200  10  10]
 [ 10  10  10  10  10  10   0]]
均值滤波后:[[ 10  10  10  10  10  10  10]
 [ 10  10  10  10  10  10  10]
 [ 10  10 200  10  10  10  10]
 [ 10  10 200  10  10  10  10]
 [ 10  10 200 200  10  10  10]
 [ 10  10  10  10  10  10  10]
 [ 10  10  10  10  10  10  10]]

  • Effet de filtrage : il peut mieux éliminer le bruit du sel et du poivre, tandis que la luminosité globale de l'image reste inchangée, et l'effet de suppression du bruit du sel et du poivre est bon.
Figure 2.4.3. Résultats du flou médian

(5)中值滤波对不同噪声的去除效果(L'effet de flou du filtrage moyen avec des noyaux de convolution de différentes tailles a été vérifié et ne sera pas répété ultérieurement)

  • code
# 作者:OpenCv机器视觉
# 时间:2023/1/25
# 功能:随机噪声+椒盐噪声+高斯噪声对比 and 不同滤波核大小对图像的模糊降噪模糊效果 and 中值滤波对随机噪声、椒盐噪声、高斯噪声的去噪效果


import cv2 as cv
import numpy as np

# 函数说明,ctrl点cv.medianBlur就可以进入,里面有说明函数如何使用以及参数含义
"""
    medianBlur(src, ksize[, dst]) -> dst
    .   The function smoothes an image using the median filter 
    .   @param src input 1-, 3-, or 4-channel image; when ksize is 3 or 5, the image depth should be
    .   CV_8U, CV_16U, or CV_32F, for larger aperture sizes, it can only be CV_8U.
    .   @param dst destination array of the same size and type as src.
    .   @param ksize aperture linear size; it must be odd and greater than 1, for example: 3, 5, 7 ...

    """

# 添加高斯噪声
def make_gauss_noise(image, mean=0, sigma=25):
    image = np.array(image / 255, dtype=float)  # 将原始图像的像素值进行归一化,因为高斯分布是在0-1区间
    # 创建一个均值为mean,方差为sigma,呈高斯分布的图像矩阵
    noise = np.random.normal(mean, sigma / 255.0, image.shape)
    add = image + noise  # 将噪声和原始图像进行相加得到加噪后的图像
    img_noise= np.clip(add, 0.0, 1.0)
    img_noise = np.uint8(img_noise * 255.0)


    return img_noise
# 添加随机噪声
def make_random_noise(img_noise, num=100):

    # 获取图片h,w,c参数
    h,w,c = img_noise.shape

    # 加噪声
    for i in range(num):
        b = np.random.randint(0,255)    # 每个通道数值随机生成
        g = np.random.randint(0,255)
        r = np.random.randint(0,255)

        x = np.random.randint(0, w)  # 随机生成指定范围的整数
        y = np.random.randint(0, h)
        img_noise[y, x] = (b,g,r)   # opencv读取图像后,是BGR格式


    return img_noise
# 添加椒盐噪声
def make_salt_pepper_noise(img_noise):
    # 进行添加噪声
    for i in range(1000):
        # 椒(黑色)噪点,随机坐标
        xb = np.random.randint(0, w)
        yb = np.random.randint(0, h)
        # 盐(白色)噪点,随机坐标
        xw = np.random.randint(0, w)
        yw = np.random.randint(0, h)

        # 根据坐标进行添加早点
        img_noise[yb, xb, :] = 255  # h,w,c,第一个参数是高度、第二个参数是宽度、第三个参数是通道数
        img_noise[yw, xw, :] = 0  # h,w,c,第一个参数是高度、第二个参数是宽度、第三个参数是通道数

    return img_noise



# 读取图片
img = cv.imread(".\\img\\lena.jpg")

# 获取图片,h,w,c参数
h,w,c=img.shape


# 添加随机噪声、椒盐噪声、高斯噪声
img_rn= make_random_noise(img.copy(),2000)
img_spn = make_salt_pepper_noise(img.copy())
img_gn = make_gauss_noise(img.copy())
img_noise_stack = np.hstack([img,img_rn,img_spn,img_gn])


# 不同大小的滤波核的滤波效果
blurred_3 = cv.medianBlur(img_spn, 3)
blurred_5 = cv.medianBlur(img_spn,5) # 对本张图片,5x5的滤波效果较好
blurred_7 = cv.medianBlur(img_spn, 7)
img_diffsize_stack = np.hstack([img,blurred_3,blurred_5,blurred_7])

# # 对随机噪声、椒盐噪声、高斯噪声噪声图进行中值模糊
blurred_rn5  = cv.medianBlur(img_rn,5)
blurred_spn5 = cv.medianBlur(img_spn, 5)
blurred_gn5 = cv.medianBlur(img_gn, 5)
img_diffnoise_stack = np.hstack([img,blurred_rn5,blurred_spn5,blurred_gn5])



# 垂直拼凑图片
stack = np.vstack([img_noise_stack,img_diffsize_stack,img_diffnoise_stack])    #

# 显示图像
cv.namedWindow("img", 0)
cv.imshow("img", stack)
cv.waitKey(0)
  • Effet : Le filtrage médian est très efficace pour éliminer le bruit du sel et du poivre (对高斯滤波的效果勉强还算可以,效果也跟高斯噪声参数设置有关,如噪声类型、质量). L'effet de suppression des différentes tailles de noyau de convolution est également très bon, la luminosité de l'image reste inchangée et les détails originaux de l'image sont conservés.
Figure 2.4.4. Comparaison de la suppression de différents bruits par filtrage médian

2.5 Flou gaussien

2.5.1 Flou gaussien

(1)原理:Contrairement au filtrage moyen (remplacement de la valeur de pixel du point central de la fenêtre par toutes les valeurs de pixels de la fenêtre 均值), le poids de chaque pixel est le même et les poids de la distribution gaussienne sont basés sur la distribution gaussienne. plus le point central de la fenêtre est proche, plus le poids est élevé. Plus la valeur est grande, plus l'impact sur le pixel central est important.
(2)应用:Lissez les images et éliminez le bruit gaussien. :
(3)高斯分布概率密度分布函数: (具体原理见推荐阅读文章,里面讲得比较仔细,这里只是大致讲解一下)

  • 一维:y=f(x),μ \muμ (moyenne) détermine le centre de symétrie,σ \sigmaσ (écart type),σ 2 \sigma^2p2 (variance) détermine la forme de la distribution - plus elle est grande, plus elle est épaisse (plus la variance est grande, plus l'écart par rapport à la moyenne est grand, plus l'image est large, la zone est de 1, donc la hauteur est inférieure, il s'agit donc de gros morceaux). De la même manière, plus il y en a, plus il est fin et grand.

Figure 2.5.1.1 Formule de densité de probabilité de distribution gaussienne unidimensionnelle

  • Image de distribution de probabilité de distribution normale unidimensionnelle :

Figure 2.5.1.2 Image de distribution gaussienne unidimensionnelle

  • Deux dimensions : z = f(x,y),

Figure 2.5.1.3 Formule de densité de probabilité de distribution gaussienne bidimensionnelle

  • Distribution gaussienne bidimensionnelle :

Figure 2.5.1.4 Image de distribution gaussienne bidimensionnelle (image)

  • Lorsque la variance σ \sigma dans chaque directionLorsque σ sont tous égaux, l’expression peut être simplifiée comme suit :

Figure 2.5.1.5 Formule de densité de probabilité de distribution gaussienne bidimensionnelle (image)

  • Le noyau gaussien généré par la distribution gaussienne est le suivant : plus le noyau du filtre est proche du centre, plus la proportion de poids est grande, et plus on s'en éloigne, plus la proportion de poids est petite. À partir de la seule dimension X/Y, on peut le voir qu'elle est très similaire à la distribution gaussienne.

Figure 2.5.1.6 Formule de densité de probabilité de distribution gaussienne bidimensionnelle (image)

  • Lien du code de génération du noyau gaussien : reportez-vous à ce lien (lien de référence) et ajoutez également des notes à tout le monde :
# 作者:OpenCv机器视觉
# 时间:2023/1/26
# 功能:生成高斯核
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt



def dnorm(x, mu, sd):
    """
    :param x:输入距离
    :param mu: 均值
    :param sd: 标准差
    """
    # 利用一维高斯分布函数进行计算
    return 1 / (np.sqrt(2 * np.pi) * sd) * np.e ** (-np.power((x - mu) / sd, 2) / 2)


def gaussian_kernel(size, sigma=1, verbose=False):
    # 高斯核其他像素点到中心点的距离,距离值之所以是这么计算,大家可以自行了解欧式距离等距离概念。
    kernel_1D = np.linspace(-(size // 2), size // 2, size)  # [-1.  0.  1.]

    # 根据距离,生成高斯分布的权重
    for i in range(size):                   #  [0.21296534 0.26596152 0.21296534]
        kernel_1D[i] = dnorm(kernel_1D[i], 0, sigma)


    # 滤波核是二维,且是实(数)对称矩阵,所以两个1维函数转置(对于1维结果还是1维,猜这里增加了转置可能是为了保证多维度计算的的对应)
    kernel_2D = np.outer(kernel_1D.T, kernel_1D.T)
    """
       Given two vectors, ``a = [a0, a1, ..., aM]`` and
    ``b = [b0, b1, ..., bN]``,
    the outer product [1]_ is::

      [[a0*b0  a0*b1 ... a0*bN ]
       [a1*b0    .
       [ ...          .
       [aM*b0            aM*bN ]]

    """

    # 进行归一化,卷积神经网络CNN中常对数据进行归一化,一方面是为了减少计算量,同时减少样本差异,归一化的方式也有多种,大家后续会学到
    kernel_2D *= 1.0 / kernel_2D.max()



    # 可以将像素以不同颜色进行显示,全总越大,颜色越深
    if verbose:
        plt.imshow(kernel_2D, interpolation='none', cmap='gray')   # 设置颜色
        plt.title("Image")
        plt.show()

    return kernel_2D

img_kernel = gaussian_kernel(3,1.5,1)
# 显示图像
cv.namedWindow("img", 0)
cv.imshow("img", img_kernel)
cv.waitKey(0)

(4)原理图解:(Après réflexion, j'ai décidé de réaliser une opération de simulation)

  • 1. Étapes :
    1) Générer un noyau de convolution gaussienne : la distribution gaussienne génère des poids -> normalisation
    2) Créer des images -> convolution

  • 2. Semblables à floues, lors du filtrage, les idées sont similaires et tout le monde doit les connecter en série pour comprendre.


Figure 2.5.1.6 Principe du filtre gaussien

  • 3. Code de vérification du principe :(利用pytorch框架进行卷积运算,如果大家还没按照环境,可以根据第一章进行安装) :
# 作者:OpenCv机器视觉
# 时间:2023/1/26
# 功能:高斯原理演示

import cv2 as cv
import numpy as np
import torch
import torch.nn.functional  as F

# 高斯分布概率密度计算
def dnorm(x, mu, sd):
    """
    :param x:输入距离
    :param mu: 均值
    :param sd: 标准差
    """
    # 利用一维高斯分布函数进行计算
    return 1 / (np.sqrt(2 * np.pi) * sd) * np.e ** (-np.power((x - mu) / sd, 2) / 2)
# 获取高斯核
def gaussian_kernel(size, sigma=1, verbose=False):
    # 高斯核其他像素点到中心点的距离,距离值之所以是这么计算,大家可以自行了解欧式距离等距离概念。
    kernel_1D = np.linspace(-(size // 2), size // 2, size)  # [-1.  0.  1.]

    # 根据距离,生成高斯分布的权重
    for i in range(size):                   #  [0.21296534 0.26596152 0.21296534]
        kernel_1D[i] = dnorm(kernel_1D[i], 0, sigma)


    # 滤波核是二维,且是实(数)对称矩阵,所以两个1维函数转置(对于1维结果还是1维,猜这里增加了转置可能是为了保证多维度计算的的对应)
    kernel_2D = np.outer(kernel_1D.T, kernel_1D.T)
    """
       Given two vectors, ``a = [a0, a1, ..., aM]`` and
    ``b = [b0, b1, ..., bN]``,
    the outer product [1]_ is::

      [[a0*b0  a0*b1 ... a0*bN ]
       [a1*b0    .
       [ ...          .
       [aM*b0            aM*bN ]]

    """

    # 进行归一化,卷积神经网络CNN中常对数据进行归一化,一方面是为了减少计算量,同时减少样本差异,归一化的方式也有多种(除sum或者最大值,大家后续会学到
    # kernel_2D *= 1.0 / kernel_2D.max()    # x = x*x/max归一化
    print("归一化前:\n",kernel_2D)
    kernel_2D = kernel_2D / kernel_2D.sum()    # x = x*sum(x)归一化
    print("sum(kernel):" ,kernel_2D.sum())      # 归一化后,sum()=1,也就是图片总体亮度不变
    print("归一化后:\n",kernel_2D)


    return kernel_2D



# 获取高斯核
kernel = gaussian_kernel(3,1.5,1)


# 定义tensor二维数组,因为后面要卷积运算
input =torch.tensor([[255, 10, 10, 10, 10, 10, 10],
                    [10, 10, 10, 200, 10, 10, 10],
                    [10, 10, 200, 200, 10, 10, 10],
                    [10, 255, 10, 200, 10, 10, 10],
                    [10, 10, 10, 200, 10, 10, 10],
                    [10, 10, 200, 200, 200, 10, 10],
                    [10, 10, 10, 10, 10, 10, 0]
                    ],dtype=torch.float64)
# 转为图片,需要(h,w,c)格式,同时uint8
input_img = torch.reshape(input,(7,7))
input_img = np.array(input_img,np.uint8)


# 卷积前需要转为tensor格式
kernel = torch.tensor(kernel)   # np转tensor

# 转为卷积计算格式,batch_size,chancle,height,weight
input = torch.reshape(input,(1,1,7,7))
kernel = torch.reshape(kernel,(1,1,3,3))
print("input:\n",input)
print("kernel:\n",kernel)

# 卷积,为了保证输出大小不变,进行填充
output = F.conv2d(input,kernel,stride=1,padding=1)
output = torch.reshape(output,(7,7))    # 将维度转为7x7
output= np.array(output,np.uint8)      # 转为np格式,以及无符号Int类型,用于图片显示

blurred = cv.GaussianBlur(input_img, (3, 3), 0)
stack1 = np.hstack([input_img,output,blurred])
print("output:\n",output)
cv.namedWindow("img", 0)
cv.imshow("img", stack1)
cv.waitKey(0)

  • 4. Résultats d'exécution :

归一化前:
 [[0.04535423 0.05664058 0.04535423]
 [0.05664058 0.07073553 0.05664058]
 [0.04535423 0.05664058 0.04535423]]
sum(kernel): 1.0000000000000002
归一化后:
 [[0.09474166 0.11831801 0.09474166]
 [0.11831801 0.14776132 0.11831801]
 [0.09474166 0.11831801 0.09474166]]
input:
 tensor([[[[255.,  10.,  10.,  10.,  10.,  10.,  10.],
          [ 10.,  10.,  10., 200.,  10.,  10.,  10.],
          [ 10.,  10., 200., 200.,  10.,  10.,  10.],
          [ 10., 255.,  10., 200.,  10.,  10.,  10.],
          [ 10.,  10.,  10., 200.,  10.,  10.,  10.],
          [ 10.,  10., 200., 200., 200.,  10.,  10.],
          [ 10.,  10.,  10.,  10.,  10.,  10.,   0.]]]], dtype=torch.float64)
kernel:
 tensor([[[[0.0947, 0.1183, 0.0947],
          [0.1183, 0.1478, 0.1183],
          [0.0947, 0.1183, 0.0947]]]], dtype=torch.float64)
output:
 [[ 40  35  24  29  24   6   4]
 [ 35  51  72  78  50  10   6]
 [ 30  61 119 105  68  10   6]
 [ 35  64 119 101  68  10   6]
 [ 30  56 114 119  90  28   6]
 [  6  32  78 105  78  31   5]
 [  4  24  47  65  47  23   3]]

  • 5. Effet d'exécution : L'effet de flou est fondamentalement le même, mais il existe une légère différence par rapport à l'API de flou gaussien d'opencv. Cela peut être causé par différents paramètres de variance, ou cela peut être dû à différentes fonctions de normalisation, mais l'effet global le résultat est le même.
Figure 2.5.1.7 Comparaison de simulation gaussienne

6. Analyse des effets : On peut voir intuitivement que les valeurs des pixels dans le coin supérieur gauche et la dernière rangée sont à l'origine des pixels noirs car il y a des pixels plus clairs autour d'eux. Après le filtrage gaussien, les valeurs des pixels deviennent plus élevées. Le contraste global des signes de l'image diminue et devient plus lisse et flou.

Figure 2.5.1.8 Créer des images et appliquer un effet de filtrage gaussien

(4)高斯模糊实验代码:Plusieurs codes de filtrage sont généralement les mêmes. Ce qui a changé, c'est la fonction de filtrage. Pour copier et utiliser en premier, il est préférable de tous les coller.

# 作者:OpenCv机器视觉
# 时间:2023/1/25
# 功能:随机噪声+椒盐噪声+高斯噪声对比 and 不同滤波核大小对图像的模糊降噪模糊效果 and 高斯滤波对随机噪声、椒盐噪声、高斯噪声的去噪效果


import cv2 as cv
import numpy as np

# 函数说明,ctrl点cv.medianBlur就可以进入,里面有说明函数如何使用以及参数含义
"""
    GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)
    .   The function convolves the source image with the specified Gaussian kernel.
    .   @param src input image; the image can have any number of channels, which are processed
    .   independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
    .   @param dst output image of the same size and type as src.
    .   @param ksize Gaussian kernel size. 
    .   @param sigmaX Gaussian kernel standard deviation in X direction.
    .   @param sigmaY Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be
    .   equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width and ksize.height,
    .   @param borderType pixel extrapolation method, see #BorderTypes.
    .   @sa  sepFilter2D, filter2D, blur, boxFilter, bilateralFilter, medianBlur
"""

# 添加高斯噪声
def make_gauss_noise(image, mean=0, sigma=15):
    image = np.array(image / 255, dtype=float)  # 将原始图像的像素值进行归一化,因为高斯分布是在0-1区间
    # 创建一个均值为mean,方差为sigma,呈高斯分布的图像矩阵
    noise = np.random.normal(mean, sigma / 255.0, image.shape)
    add = image + noise  # 将噪声和原始图像进行相加得到加噪后的图像
    img_noise= np.clip(add, 0.0, 1.0)
    img_noise = np.uint8(img_noise * 255.0)


    return img_noise
# 添加随机噪声
def make_random_noise(img_noise, num=100):

    # 获取图片h,w,c参数
    h,w,c = img_noise.shape

    # 加噪声
    for i in range(num):
        b = np.random.randint(0,255)    # 每个通道数值随机生成
        g = np.random.randint(0,255)
        r = np.random.randint(0,255)

        x = np.random.randint(0, w)  # 随机生成指定范围的整数
        y = np.random.randint(0, h)
        img_noise[y, x] = (b,g,r)   # opencv读取图像后,是BGR格式


    return img_noise
# 添加椒盐噪声
def make_salt_pepper_noise(img_noise):
    # 进行添加噪声
    for i in range(1000):
        # 椒(黑色)噪点,随机坐标
        xb = np.random.randint(0, w)
        yb = np.random.randint(0, h)
        # 盐(白色)噪点,随机坐标
        xw = np.random.randint(0, w)
        yw = np.random.randint(0, h)

        # 根据坐标进行添加早点
        img_noise[yb, xb, :] = 255  # h,w,c,第一个参数是高度、第二个参数是宽度、第三个参数是通道数
        img_noise[yw, xw, :] = 0  # h,w,c,第一个参数是高度、第二个参数是宽度、第三个参数是通道数

    return img_noise



# 读取图片
img = cv.imread(".\\img\\lena.jpg")
# 获取图片,h,w,c参数
h,w,c=img.shape



# 添加随机噪声、椒盐噪声、高斯噪声
img_rn= make_random_noise(img.copy(),2000)
img_spn = make_salt_pepper_noise(img.copy())
img_gn = make_gauss_noise(img.copy())
img_noise_stack = np.hstack([img,img_rn,img_spn,img_gn])


# 不同大小的滤波核的滤波效果
blurred_3 = cv.GaussianBlur(img_gn, (3,3),0)
blurred_5 = cv.GaussianBlur(img_gn,(5,5),0) # 对本张图片,5x5的滤波效果较好
blurred_7 = cv.GaussianBlur(img_gn, (7,7),0)
img_diffsize_stack = np.hstack([img,blurred_3,blurred_5,blurred_7])

# # 对随机噪声、椒盐噪声、高斯噪声噪声图进行高斯模糊
blurred_rn5  = cv.GaussianBlur(img_rn,(5,5),0)
blurred_spn5 = cv.GaussianBlur(img_spn, (5,5),0)
blurred_gn5 = cv.GaussianBlur(img_gn, (5,5),0)
img_diffnoise_stack = np.hstack([img,blurred_rn5,blurred_spn5,blurred_gn5])



# 垂直拼凑图片
stack = np.vstack([img_noise_stack,img_diffsize_stack,img_diffnoise_stack])    #

# 显示图像
cv.namedWindow("img", 0)
cv.imshow("img", stack)
cv.waitKey(0)

(5)效果:

  • Comme le montre la figure 12, le filtrage gaussien a un très bon effet dans la suppression du bruit gaussien.
Figure 2.5.1.9 Comparaison de la suppression de différents bruits par filtrage gaussien

2.5.2 Flou Stackblur (approximation du flou gaussien)

(1)应用:Pour les images super-résolution, si le noyau de convolution est trop grand, le calcul sera très lent. Par conséquent, stackblur est un algorithme d'optimisation proposé pour remédier au fonctionnement lent des grands noyaux de convolution. Portail d'introduction à l'algorithme Stackblur
(2)算法介绍:

2.6 Flou bilatéral

(1)原理:Le filtrage bilatéral est une technologie de traitement d'image qui améliore la qualité de l'image. Il peut conserver efficacement les détails de l'image tout en supprimant le bruit . Il détermine la valeur des pixels en fonction de la valeur de gris de l'image en calculant la distance pondérée gaussienne entre chaque pixel de l'image et ses pixels voisins , rendant ainsi les bords de l'image plus clairs et le bruit plus supprimé.简单来说,就是高斯模糊没有考虑到相邻像素的相似值,图像会总体比较模糊,双边滤波就是为了解决边缘模糊问题。

(2)应用:Par rapport à l'opération de flou précédente, qui brouille les bords du contour, le flou bilatéral non seulement floute l'image mais préserve également bien les bords du contour. Il peut être utilisé pour le resurfaçage de la peau , les contours clairs et le débruitage interne.

(3)特点:Avantages : réduit les bruits indésirables tout en conservant les détails du contour des bords ; Inconvénients : calcul lent

(4)代码:

# 作者:OpenCv机器视觉
# 时间:2023/1/27
# 功能:随机噪声+椒盐噪声+高斯噪声对比 and 不同Sigma大小对图像的模糊降噪模糊效果 and 双边滤波对随机噪声、椒盐噪声、高斯噪声的去噪效果


import cv2 as cv
import numpy as np


# 函数说明,ctrl点cv.bilateralFilter就可以进入,里面有说明函数如何使用以及参数含义,

"""

    bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)
     @brief Applies the bilateral filter to an image.
     
    .   The function 
    .   bilateralFilter can reduce unwanted noise very well while keeping edges fairly sharp. 
    .   However, it is very slow compared to most filters.
    .   
    .   src: 输入图像,可以是Mat类型,图像必须是8位或浮点型单通道、三通道的图像。 
    .  sigmaColor: 颜色空间过滤器的sigma值,这个参数的值越大,表明该像素邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域。 
    .   sigmaSpace: 坐标空间中滤波器的sigma值,如果该值较大,则意味着越远的像素将相互影响,从而使更大的区域中足够相似的颜色获取相同的颜色。

    .   _Filter size_: Large filters (d \> 5) are very slow, so it is recommended to use d=5 for real-time
    .   applications, and perhaps d=9 for offline applications that need heavy noise filtering.
    
    .   _Sigma values_: For simplicity, you can set the 2 sigma values to be the same. If they are small (\<
    .   10), the filter will not have much effect, whereas if they are large (\> 150), they will have a very
    .   strong effect, making the image look "cartoonish".

"""


# 添加高斯噪声
def make_gauss_noise(image, mean=0, sigma=15):
    image = np.array(image / 255, dtype=float)  # 将原始图像的像素值进行归一化,因为高斯分布是在0-1区间
    # 创建一个均值为mean,方差为sigma,呈高斯分布的图像矩阵
    noise = np.random.normal(mean, sigma / 255.0, image.shape)
    add = image + noise  # 将噪声和原始图像进行相加得到加噪后的图像
    img_noise= np.clip(add, 0.0, 1.0)
    img_noise = np.uint8(img_noise * 255.0)


    return img_noise
# 添加随机噪声
def make_random_noise(img_noise, num=100):

    # 获取图片h,w,c参数
    h,w,c = img_noise.shape

    # 加噪声
    for i in range(num):
        b = np.random.randint(0,255)    # 每个通道数值随机生成
        g = np.random.randint(0,255)
        r = np.random.randint(0,255)

        x = np.random.randint(0, w)  # 随机生成指定范围的整数
        y = np.random.randint(0, h)
        img_noise[y, x] = (b,g,r)   # opencv读取图像后,是BGR格式


    return img_noise
# 添加椒盐噪声
def make_salt_pepper_noise(img_noise):
    # 进行添加噪声
    for i in range(1000):
        # 椒(黑色)噪点,随机坐标
        xb = np.random.randint(0, w)
        yb = np.random.randint(0, h)
        # 盐(白色)噪点,随机坐标
        xw = np.random.randint(0, w)
        yw = np.random.randint(0, h)

        # 根据坐标进行添加早点
        img_noise[yb, xb, :] = 255  # h,w,c,第一个参数是高度、第二个参数是宽度、第三个参数是通道数
        img_noise[yw, xw, :] = 0  # h,w,c,第一个参数是高度、第二个参数是宽度、第三个参数是通道数

    return img_noise



# 读取图片
img = cv.imread(".\\img\\lena.jpg")
# 获取图片,h,w,c参数
h,w,c=img.shape


# 添加随机噪声、椒盐噪声、高斯噪声
img_rn= make_random_noise(img.copy(),2000)
img_spn = make_salt_pepper_noise(img.copy())
img_gn = make_gauss_noise(img.copy())
img_noise_stack = np.hstack([img,img_rn,img_spn,img_gn])


# sigmaColor不同情况下的滤波效果
blurred_50 = cv.bilateralFilter(img, d=0, sigmaColor=50, sigmaSpace=15)# 双边保留滤波,经可能模糊其他背景,但是边缘保留下来。d 像素的领域直径,由颜色空间标准差sigmaColor(越大越好),坐标空间的标准差sigmaSpace(越小越好),决定
blurred_100 = cv.bilateralFilter(img, d=0, sigmaColor=100, sigmaSpace=15)
blurred_150 = cv.bilateralFilter(img, d=0, sigmaColor=150, sigmaSpace=15)
img_diffsize_stack = np.hstack([img,blurred_50,blurred_100,blurred_150])

# # 对随机噪声、椒盐噪声、高斯噪声噪声图进行双边滤波
blurred_rn5  = cv.bilateralFilter(img_rn, d=0, sigmaColor=50, sigmaSpace=15)
blurred_spn5 = cv.bilateralFilter(img_spn, d=0, sigmaColor=50, sigmaSpace=15)
blurred_gn5 = cv.bilateralFilter(img_gn, d=0, sigmaColor=50, sigmaSpace=15)
img_diffnoise_stack = np.hstack([img,blurred_rn5,blurred_spn5,blurred_gn5])



# 垂直拼凑图片
stack = np.vstack([img_diffsize_stack,img_diffnoise_stack])    #

# 显示图像
cv.namedWindow("img", 0)
cv.imshow("img", stack)
cv.waitKey(0)

(5)效果:Plus le réglage du paramètre sc est grand, plus la gamme de couleurs est prise en compte et plus l'image est floue ; en même temps, elle a un bon effet de suppression du bruit gaussien (具备高斯模糊分配权重的模糊特点,还具备保留边缘优点)tout en conservant les bords.

Figure 2.5.1.10 Effet de filtrage bilatéral

(6) 推荐阅读文章:

1. Filtre bilatéral
1. Filtre bilatéral Compréhension populaire du filtre bilatéral
3. Filtrage bilatéral et implémentation du code

2.7 Résumé

均值滤波:随机噪声
中值滤波:椒盐噪声
高斯滤波:高斯噪声
双边滤波:高斯噪声、在人物美艳磨皮中比较有效果。
自定义滤波:图像锐化、图像增强

2.8 Articles de lecture recommandés

1. Analyse des causes du flou de mouvement/maculage
2. Analyse en termes simples : cv2.getRotationMatrix2D

3. Le principe du flou gaussien
4. Notes python+OpenCv (9) : filtrage moyen
5. Filtrage médian (Filtrage médian)
6. Bien comprendre le flou moyen, le flou médian, le flou gaussien, le flou bilatéral)
7. Le flou gaussien)
8. Filtrage gaussien)
9. Distribution gaussienne multidimensionnelle
10. Apprentissage pas à pas CV2-2 : explication détaillée de cv2.GaussianBlur()
11. OpenCv

Remarque: Les connaissances liées à la matrice de rotation sont utilisées pour créer un flou de mouvement.Ce cv.getRotationMatrix2Dpoint de connaissance est également couramment utilisé dans la transformation de perspective et la transformation de rotation dans l'amélioration des données d'apprentissage profond . Pour l’instant, vous n’avez pas à vous soucier de modifier les points de connaissance. Vous pourrez probablement découvrir à quoi ressemble le flou de mouvement. Une fois les bases apprises, j'apprendrai cv.getRotationMatrix2Dles connaissances pertinentes basées sur l'application du projet, je les mettrai également à jour et publierai un article d'analyse des principes pour le prouver à partir de la génération de lignes. Un article pour résoudre la théorie de la transformation de perspective + application pratique (sera mis à jour ultérieurement)

3. Détection des bords

(1) Citation : Le débruitage précédent est un maillon de base important dans le prétraitement de l'image. En termes de détection des contours, il commence principalement à segmenter l'image prétraitée. La détection des contours est largement utilisée et les algorithmes de détection des contours sont souvent utilisés dans l'inspection des plaques d'immatriculation, la segmentation des routes et la correction de documents.

Figure 3.1 Détection de ligne de voie

Figure 3.2 Détection de documents

(2) Méthode de mise en œuvre : La détection des contours est similaire à la convolution CNN, ainsi qu'à la convolution de divers filtres de flou. Ce sont tous des modèles de convolution qui opèrent sur l'image. C'est juste que les modèles sont différents. Dans la détection des contours, elle peut être divisée en plusieurs opérateurs. Ce qui suit présente ses types d’opérateurs et ses effets d’implémentation un par un. (La notion d'opérateurs est évoquée au chapitre 3. )

Figure 3.3 Explication de l'opérateur

(3) Cet article explique d'abord les différents opérateurs de détection de bords un par un, et enfin résume et compare les avantages et les inconvénients de chaque opérateur. Dans le même temps, de nombreux algorithmes traditionnels existants dans opencv ne sont pas très robustes et la plupart d'entre eux doivent être améliorés et appliqués (vous pouvez rechercher des articles sur l'amélioration des algorithmes), mais l'apprentissage de ces algorithmes est la prémisse de base. Les bases peuvent vous tenir sur les épaules des géants. Ce n'est qu'en faisant cela que nous pourrons écrire de meilleurs algorithmes.

3.1 Opérateur Robert

(1)原理:Opérateur qui utilise des opérateurs de différence locale pour trouver des arêtes (局部区域内,相邻两个像素点值得变化,其导数可以用来衡量像素变化速度,如果变换较大,则大概率是边缘处). Il peut être divisé en deux modèles, un dans la direction x et un dans la direction y.

(2)特点:La capacité de suppression du bruit est faible. Il détecte mieux les lignes horizontales et verticales que les arcs (与Sobel有些相反,见下面实验). Les bords ne sont pas très lisses, donc le positionnement n'est pas très précis.

(3)算子介绍:

Figure 3.1.1 Coordonnées de l'opérateur

  • Opérateur Gx

G x = ( 1 0 0 − 1 ) (4) G_x = \ \begin{pmatrix} 1 & 0 \\ 0 & -1 \\ \end{pmatrix} \tag{4}gx= (100 1)( 4 )

  • Opérateur Gy
    G x = ( 0 1 − 1 0 ) (5) G_x = \ \begin{pmatrix} 0 & 1 \\ -1 & 0 \\ \end{pmatrix} \tag{5}gx= (0 110)( 5 )

  • Opérateur G
    G = G x 2 + G y 2 (6) G= \sqrt{G_x^2+G_y^2} \tag{6}g=gX2+goui2 ( 6 )

  • Explication de la thèse :

Figure 3.1.2 Description du papier Gx, Gy, G

(4)检测效果:

  • 1.Image originale
    Figure 3.1.3 Image originale de l'expérience


    2. À propos, afin d'observer l'effet de suppression du bruit de l'opérateur Sobert, trois bruits différents sont ajoutés à l'image : image originale (左上), bruit aléatoire (右上), bruit sel et poivre (左下)et bruit gaussien (右下).
    Figure 3.1.4 Ajouter une carte de bruit

  • 3. Comparaison avant et après débruitage : Robert算子抑制噪声较弱si l'image contient beaucoup de bruit, l'effet de détection des contours sera considérablement réduit. Il doit donc être débruité avant la détection des contours.

Figure 3.1.4 Ajouter une carte de bruit

    1. G x G_xgxDétection d'opérateur, G x G_xgxDétection d'opérateur, G x G_xgxComparaison de détection de l'opérateur : Les lignes dans le sens diagonal formées par 0
      蓝色框: chez l'opérateur sont bien détectées ; en même temps, les lignes obliques de 135° et 45° ne peuvent pas être détectées (vous pouvez vous référer au code principe ci-dessous pour comprendre) ; opérateur x ou opérateur y Les lignes de détection d'arc ne sont pas assez continues, mais après pondération des deux opérateurs, la détection est encore relativement complète ; pour certaines détections de formes relativement régulières (et sans bruit parasite, si nécessaire, un débruitage est nécessaire), en fait, Robert calcule que l'effet de détection des contours est toujours bon, mais pour certaines images complexes, telles que des lignes et des arcs plus diagonaux, la détection sera manquée.
      绿色框:
      黄色框:
      总体来说:

Figure 3.1.5 Effet de détection des bords des opérateurs Gx, Gy, G

  • 5.code de détection :
"""
作者:OpenCv机器视觉
时间:2023/1/31
功能:1.利用roberts算子进行边缘检测,看GX、Gy、G算子检测不同角度直线+圆弧下的效果;
    2.添加噪声以及除噪后的实验对比

"""
import cv2 as cv
import numpy as np


# 添加高斯噪声
def make_gauss_noise(image, mean=0, sigma=15):
    image = np.array(image / 255, dtype=float)  # 将原始图像的像素值进行归一化,因为高斯分布是在0-1区间
    # 创建一个均值为mean,方差为sigma,呈高斯分布的图像矩阵
    noise = np.random.normal(mean, sigma / 255.0, image.shape)
    add = image + noise  # 将噪声和原始图像进行相加得到加噪后的图像
    img_noise= np.clip(add, 0.0, 1.0)
    img_noise = np.uint8(img_noise * 255.0)


    return img_noise
# 添加随机噪声
def make_random_noise(img_noise, num=300):

    # 获取图片h,w,c参数
    h,w,c = img_noise.shape

    # 加噪声
    for i in range(num):
        b = np.random.randint(0,255)    # 每个通道数值随机生成
        g = np.random.randint(0,255)
        r = np.random.randint(0,255)

        x = np.random.randint(0, w)  # 随机生成指定范围的整数
        y = np.random.randint(0, h)
        img_noise[y, x] = (b,g,r)   # opencv读取图像后,是BGR格式


    return img_noise
# 添加椒盐噪声
def make_salt_pepper_noise(img_noise):
    h,w = img_noise.shape[:2]
    print(h,w)
    # 进行添加噪声
    for i in range(500):
        # 椒(黑色)噪点,随机坐标
        xb = np.random.randint(0, w)
        yb = np.random.randint(0, h)
        # 盐(白色)噪点,随机坐标
        xw = np.random.randint(0, w)
        yw = np.random.randint(0, h)

        # 根据坐标进行添加早点
        img_noise[yb, xb, :] = 255  # h,w,c,第一个参数是高度、第二个参数是宽度、第三个参数是通道数
        img_noise[yw, xw, :] = 0  # h,w,c,第一个参数是高度、第二个参数是宽度、第三个参数是通道数

    return img_noise









# 左上角原图、右上角随机噪声、左下角椒盐噪声、右下角高斯噪声
img= cv.imread(".\\img\\1.jpg")
h,w,c = img.shape
mh,mw = h//2,w//2
img_top_r = img[0:mh,mw:w:]
img_under_l=img[mh:h,0:mw,:]
img_under_r = img[mh:h,mw:w:,:]
# 加噪声
# img_top_r = make_random_noise(img_top_r)
# img_under_l = make_salt_pepper_noise(img_under_l)
# img_under_r = make_gauss_noise(img_under_r)
# # 去噪
# img_top_r = cv.blur(img_top_r, (5, 5))
# img_under_l=cv.medianBlur(img_under_l, 3)
# img_under_r = cv.GaussianBlur(img_under_r,(5,5),0)

img[0:mh,mw:w:] = img_top_r
img[mh:h,0:mw,:] = img_under_l
img[mh:h,mw:w:,:] = img_under_r



gray= cv.cvtColor(img,cv.COLOR_BGR2GRAY)        # 转灰度
ret,binary = cv.threshold(gray,10,255,cv.THRESH_BINARY)   # 二值化

# robert算子定义
kernel_x = np.array([[1,0],[0,-1]],np.int8)
kernel_y = np.array([[0,1],[-1,0]],np.int8)

# robert算子检测
x=cv.filter2D(binary,cv.CV_16S,kernel_x)     # 可以看成卷积运算,原理通卷积但是又有些区别
y=cv.filter2D(binary,cv.CV_16S,kernel_y)    
absX = cv.convertScaleAbs(x)                # 因为算子中有-1,所以卷积后有部分是负数,需要取绝对值
absY = cv.convertScaleAbs(y)
Roberts = cv.addWeighted(absX,0.5,absY,0.5,0)   #  GX、Gy合成G
print(x[199])
print(absX[199])


stack = np.hstack([absX,absY,Roberts])

# 显示图片
cv.namedWindow("img",0)
cv.imshow("img",img)
cv.namedWindow("stack",0)
cv.imshow("stack",stack)
cv.namedWindow("Gx",0)
cv.imshow("Gx",absX)
cv.namedWindow("Gy",0)
cv.imshow("Gy",absY)
cv.namedWindow("G",0)
cv.imshow("G",Roberts)
cv.waitKey(0)

(5)边缘检测算子卷积原理演示:

  • 1. En fait, pour parler franchement, c'est le principe de la convolution, mais l'opérateur (le même que le noyau de convolution et le noyau de filtre, les noms sont différents selon les applications) est appelé un opérateur Robert.

Figure 3.1.6 Effet de la mise en œuvre du code

    1. Effet de simulation :
      Figure 3.1.6 Effet de la mise en œuvre du code

  • 3. Code de mise en œuvre :
"""
作者:OpenCv机器视觉
时间:2023/1/31
功能:模拟Robert原理

"""

import cv2 as cv
import numpy as np


# 底层原理,输出结果与cv.fliter2D的结果会发生做偏移1个像素
def robert_x_y(img,kernel):
    # 复制一张原图
    result = img.copy()

    # 对图像进行扩充1行1列,用于边缘的计算
    h, w = img.shape
    add_r = np.zeros((1,w))
    add_c = np.zeros((h+1,1))    # 后增加的需要多加多一个角点
    img = np.row_stack((img,add_r))
    img = np.column_stack((img,add_c))
    h, w = img.shape

     # 平滑图像进行卷积运算
    for i in range(h):
        for j in range(w):
            if (i+2 < h) and (j+2 < w):
                roi = img[i:i + 2, j:j + 2]
                list_robert = kernel * roi
                result[i, j] = abs(list_robert.sum())  # 求和加绝对值
                print('{' ':>9}'.format(abs(list_robert.sum())),end='') # 输出右对齐
        print()
    return  result




input = np.array([[0, 0, 0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 0, 0, 0],
                    [0, 0, 255, 255, 255, 0, 0],
                    [0, 0, 255, 255, 255, 0, 0],
                    [0, 0, 255, 255, 255, 0, 0],
                    [0, 0, 0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 0, 0, 0]
                    ],dtype=np.uint8)





# robert算子定义
kernel_x = np.array([[1,0],[0,-1]],np.int8)
kernel_y = np.array([[0,1],[-1,0]],np.int8)

# 自己实现的函数
robertx= robert_x_y(input,kernel_x)
roberty= robert_x_y(input,kernel_y)
robertxy = cv.addWeighted(robertx,0.5,roberty,0.5,0)

#调用Opencv的函数
x=cv.filter2D(input,cv.CV_16S,kernel_x)
y=cv.filter2D(input,cv.CV_16S,kernel_y)
absX = cv.convertScaleAbs(x)
absY = cv.convertScaleAbs(y)
Roberts = cv.addWeighted(absX,0.5,absY,0.5,0)

# 图片拼接
stack1 = np.hstack([robertx,roberty,robertxy])
stack2 = np.hstack([absX,absY,Roberts])
stack = np.vstack([stack1,stack2])


cv.namedWindow("input",0)
cv.imshow("input",input)

cv.namedWindow("stack",0)
cv.imshow("stack",stack)

cv.waitKey(0)

(6)推荐阅读文章:

1. Opérateur Robert pour la segmentation d'images
2. Opérateur Robert pour la détection des contours
Lien : lien

3.2 Opérateur Sobel

(1)原理:Détectez les bords en fonction des informations de dégradé de l'image.
(2)特点:Il est court dans le temps, possède une certaine immunité au bruit et a un bon effet de détection des bords.

(3)算子介绍:

  • 1. Similaire à Robert , mais le modèle d'opérateur est différent. Il est divisé en modèle horizontal (peut être compris comme noyau de convolution) et modèle vertical(两个互为转置,A[i][j]=B[j][i]) .

Figure 3.1.6 Effet de la mise en œuvre du code

(4)检测效果:
1. Testez l'image originale : Comme ci-dessus
2. Afin de mesurer la capacité anti-bruit de l'opérateur Sobel, ajoutez trois types de bruit à l'image, comme ci-dessus.
3. Comparaison avant et après débruitage : l'opérateur Sobel possède une certaine immunité au bruit.

(5)边缘检测算子卷积原理演示:
(6)推荐阅读文章:
[200 routines OpenCV] 64. Netteté de l'image - Opérateur Sobel
https://blog.csdn.net/youcans/article/details/122152278
Traitement d'image python+OpenCV (8) Détection des contours
https://blog.csdn.net/qq_40962368 /article/details/81416954
OpenCV——Détection des bords Sobel
https://blog.csdn.net/qq_36686437/article/details/120814041
Détection des bords Sobel
https://www.cnblogs.com/yibeimingyue/p /10878514.html

3.3Opérateur Scharra

(1)原理:
(2)特点:
(3)算子介绍:
(4)检测效果:
(5)边缘检测算子卷积原理演示:
(6)推荐阅读文章:

3.4 Opérateur Préwitt

(1)原理:
(2)特点:
(3)算子介绍:
(4)检测效果:
(5)边缘检测算子卷积原理演示:
(6)推荐阅读文章:

3.5 Opérateur Kirsh

(1)原理:
(2)特点:
(3)算子介绍:
(4)检测效果:
(5)边缘检测算子卷积原理演示:
(6)推荐阅读文章:

3.6 Opérateur Robinson

(1)原理:
(2)特点:
(3)算子介绍:
(4)检测效果:
(5)边缘检测算子卷积原理演示:
(6)推荐阅读文章:

3.7 Opérateur laplacien

(1)原理:
(2)特点:
(3)算子介绍:
(4)检测效果:
(5)边缘检测算子卷积原理演示:
(6)推荐阅读文章:

3.8 Opérateur Canny

(1)原理:
(2)特点:
(3)算子介绍:
(4)检测效果:
(5)边缘检测算子卷积原理演示:
(6)推荐阅读文章:

3.9 Détection des contours avec apprentissage profond

(1) Avantages :
(2) Modèle recommandé :
Comparaison de divers opérateurs différentiels pour la détection des contours (Sobel, Robert, Prewitt, Laplacian, Canny)
https://www.cnblogs.com/molakejin/p/5683372.html

Comparaison des codes de détection de contours + effets des différents opérateurs

Articles de lecture recommandés

  • Dans la détection des contours, connaissant son application, quelles méthodes existe-t-il pour réaliser la détection des contours ?Quel est l'effet de chaque méthode de détection des contours ? Quel algorithme de détection de contour est le meilleur. Ensuite pour les principes précis, vous pouvez vous référer à l’article suivant. Je mettrai ici quelques articles bien écrits que tout le monde pourra lire.

Articles de lecture recommandés

1. Traitement d'images numériques : Détection de contours (Détection de contours)
Affinage d'image Python et détection de contours (Roberts, Prewitt, Sobel, Lapllacian, Canny, LOG) >
Cas de produit réel : Implémentation de la détection de contours de documents
opérateur de détection de contours traditionnel
algorithme de détection de ligne droite Résumer plusieurs codes sources manquants dans le billet de blog sur l'algorithme de détection de ligne droite (Hough_line, LSD, FLD, EDlines, LSWMS, CannyLines, MCMLSD, LSM)

4. Opérations morphologiques

4.1 Corrosion

4.2 Extension

4.3 Fonctionnement ouvert

4.4 Opération de fermeture

4.5 chapeau haut de forme

4.6 Chapeau noir :

4.7 Dégradé morphologique :

Je suppose que tu aimes

Origine blog.csdn.net/DGWY161744/article/details/128582667
conseillé
Classement