OpenCV apprentissage des opérations d'image de base (dix): convolution et convolution opérateur

convolution

Définition de la convolution

En termes simples, un noyau effectue une sommation pondérée sur l'image, qui peut être exprimée comme

H (x, y) = \ somme _ {i = 0} ^ {M_i-1} \ somme _ {j = 0} ^ {M_j-1} I (x + i-a_i, y + j-a_j) K (i, j)

Le point d'ancrage du noyau de convolution fait référence au point de sortie de mise à jour du noyau de convolution, qui est généralement le point central du noyau de convolution;

La taille de pas de la convolution est la distance parcourue par le noyau de convolution une fois sur l'image.

Problème de frontière de convolution

Lorsque le noyau de convolution se déplace vers la limite de la phase d'image, certaines positions du noyau de convolution dépassent la limite de l'image d'origine. À ce stade, le calcul ne peut pas être effectué et la limite de l'image d'origine doit être étendue avant le calcul.

Méthode d'expansion

BORDER_DEFAULT: Remplir avec une mise en miroir d'arête connue

BORDER_CONSTANTP: Remplissez les bords avec les pixels spécifiés

BORDER_REPLICATE: Remplissez les bords avec le plus de pixels de bord

BORDER_WRAP: Remplissez le bord avec des pixels de l'autre côté

BORDER_ISOLATED: Remplissez les bords avec 0

Opérateur de convolution

Opérateur de premier ordre

Rebert

L'opérateur de Roberts est également appelé opérateur différentiel croisé. Il s'agit d'un algorithme de gradient basé sur la différence croisée, qui détecte les lignes de bord par un calcul de différence locale. Il est couramment utilisé pour traiter des images raides et à faible bruit Lorsque le bord de l'image est proche de plus ou moins 45 degrés, l'effet de traitement de cet algorithme est plus idéal. L'inconvénient est que le positionnement du bord n'est pas précis et que la ligne de bord extraite est épaisse.

G_x = \ begin {bmatrix} +1 & 0 \\ 0 & -1 \ end {bmatrix}    G_y = \ begin {bmatrix} 0 & +1 \\ -1 & 0 \ end {bmatrix}

Prewitt

Prewitt est un opérateur différentiel pour la détection des contours de l'image dont le principe est d'utiliser la différence générée par les valeurs de gris des pixels dans une zone spécifique pour réaliser la détection des contours. Étant donné que l’opérateur Prewitt utilise un modèle 3 * 3 pour calculer les valeurs de pixels dans la zone et que le modèle de l’opérateur Robert est 2 * 2, les résultats de détection des contours de l’opérateur Prewitt sont plus évidents dans les directions horizontale et verticale que l’opérateur Robert , L'opérateur Prewitt convient pour identifier les images avec plus de bruit et une échelle de gris progressive.

G_x = \ begin {bmatrix} -1 & 0 & 1 \\ -1 & 0 & 1 \\ -1 & 0 & 1 \ end {bmatrix}   G_y = \ begin {bmatrix} -1 & -1 & -1 \\ 0 & 0 & 0 \\ 1 & 1 & 1 \ end {bmatrix}

L'opérateur Prewitt classique estime que tous les pixels avec une nouvelle valeur de gris supérieure ou égale au seuil sont des points de bord. Autrement dit, sélectionnez un seuil T approprié, si P (i, j) ≥T, alors (i, j) est le point de bord, et P (i, j) est l'image de bord. Ce type de jugement est déraisonnable et entraînera une mauvaise évaluation des points de bord, car la valeur de gris de nombreux points de bruit est également très grande, et pour les points de bord de faible amplitude, les bords sont perdus à la place.

  L'opérateur Prewitt a un effet sur la suppression du bruit. Le principe de la suppression du bruit repose sur la moyenne des pixels, mais la moyenne des pixels équivaut au filtrage passe-bas de l'image, de sorte que l'opérateur Prewitt n'est pas aussi bon que l'opérateur Roberts pour le positionnement des bords.

Sobel

L'opérateur Sobel est un opérateur différentiel discret pour la détection des bords, qui combine le lissage gaussien et la dérivation différentielle. Cet opérateur est utilisé pour calculer la valeur approximative de la luminosité de l'image. En fonction de la luminosité du bord de l'image, les points spécifiques dépassant un certain nombre dans la zone sont enregistrés comme bords. L'opérateur Sobel ajoute le concept de poids sur la base de l'opérateur Prewitt. On pense que la distance entre les points adjacents a un impact différent sur le pixel actuel. Plus le pixel est proche, plus l'impact du pixel actuel est important, de manière à réaliser l'image Nettoyez et mettez en évidence les contours des bords.

Le positionnement des bords de l'opérateur Sobel est plus précis, et il est souvent utilisé pour des images avec plus de bruit et des niveaux de gris progressifs.

G_x = \ begin {bmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \ end {bmatrix}   G_y = \ begin {bmatrix} -1 & -2 & -1 \\ 0 & 0 & 0 \\ 1 & 2 & 1 \ end {bmatrix}

L'opérateur Sobel détecte le bord en fonction de la différence de poids de gris du point de pixel vers le haut et vers le bas, les points adjacents gauche et droit, et atteint la valeur extrême au bord. Il a un effet de lissage sur le bruit et fournit des informations plus précises sur la direction du bord. Parce que l'opérateur Sobel combine le lissage gaussien et la dérivation différentielle (différenciation), le résultat aura une plus grande résistance au bruit.

La valeur approximative du gradient horizontal et vertical de chaque pixel de l'image peut être combinée avec la formule suivante pour calculer la magnitude du gradient.

G = \ sqrt {G_x ^ 2 + Gy ^ 2}

Cependant, dans l'ingénierie réelle, la formule ci-dessus est souvent remplacée par la formule suivante pour simplifier les calculs:

G = \ gauche |  G_x \ droite |  + \ gauche |  G_y \ droite |

Isotrope Sobel 算 子

  Une autre forme d'opérateur Sobel est l'opérateur (Isotropic Sobel), un opérateur moyen pondéré. Le poids est inversement proportionnel à la distance entre le point zéro et le magasin central. Lorsque les bords sont détectés dans des directions différentes, l'amplitude du gradient est la même, ce que l'on appelle communément Sobel isotrope (Isotropic Sobel) opérateur. Il existe également deux modèles, l'un pour détecter les bords horizontaux et l'autre pour détecter les bords plats verticaux. Par rapport aux opérateurs Sobel ordinaires, l'opérateur Sobel isotrope a des coefficients de pondération de position plus précis, et la magnitude du gradient est la même lors de la détection de contours dans différentes directions.

G_x = \ begin {bmatrix} -1 & 0 & 1 \\ - \ sqrt {2} & 0 & \ sqrt {2} \\ -1 & 0 & 1 \ end {bmatrix}   G_y = \ begin {bmatrix} -1 & - \ sqrt {2} & -1 \\ 0 & 0 & 0 \\ 1 & \ sqrt {2} & 1 \ end {bmatrix}

Opérateur Scharr

La différence entre l'opérateur Scharr et l'opérateur Sobel réside dans la partie de lissage. L'opérateur de lissage utilisé ici est 1/16 * [3, 10, 3], comparé à 1/4 * [1, 2, 1], le centre Le poids de l'élément est plus lourd. Cela peut être par rapport à l'image, qui est un signal plus aléatoire, et le domaine n'est pas pertinent. Par conséquent, le lissage de voisinage doit utiliser une fonction gaussienne avec un écart type relativement petit, qui est plus mince et plus grand. modèle.

  Comme l'opérateur Sobel calcule des noyaux relativement petits, la précision de la dérivée approximative est relativement faible. Par exemple, pour un opérateur Sobel 3 * 3, lorsque l'angle de gradient est proche de la direction horizontale ou verticale, son imprécision devient plus évidente. . L'opérateur Scharr est aussi rapide que l'opérateur Sobel, mais la précision est plus élevée, en particulier pour les scénarios avec des cœurs plus petits. Par conséquent, l'utilisation de filtres 3 * 3 pour réaliser l'extraction des bords de l'image est plus recommandée d'utiliser l'opérateur Scharr.

  • L'opérateur Sobel est une forme d'opérateur de filtre pour extraire les arêtes. Chacune des directions X et Y utilise un modèle et les deux modèles sont combinés pour former un opérateur de gradient. Le modèle de direction X a le plus grand impact sur le bord vertical, et le modèle de direction Y a le plus grand impact sur le bord horizontal.

  • L'opérateur Robert est une sorte d'opérateur de gradient. Il exprime le gradient par recoupement. C'est un opérateur qui utilise l'opérateur de différence locale pour trouver le bord. Il a le meilleur effet sur les images avec un bruit raide et faible.

  • L'opérateur prewitt est un opérateur moyen pondéré, qui a pour effet de supprimer le bruit, mais la moyenne des pixels équivaut au même filtrage de l'image, de sorte que l'opérateur prewitt n'est pas aussi bon que l'opérateur robert pour positionner le bord.

Opérateur de second ordre

Laplace

L'opérateur laplacien est un opérateur différentiel du second ordre dans l'espace euclidien à n dimensions, souvent utilisé dans le domaine de l'amélioration d'image et de l'extraction des bords. Il calcule les pixels du voisinage par différence de gris. Le processus de base consiste à déterminer la valeur de gris du pixel central de l'image et la valeur de gris des autres pixels qui l'entourent. Si la valeur de gris du pixel central est plus élevée, la valeur de gris du pixel central est augmentée. Réduisez le niveau de gris du pixel central, de manière à obtenir une opération de netteté de l'image. Dans le processus de mise en œuvre de l'algorithme, l'opérateur laplacien calcule les gradients dans les quatre ou huit directions du pixel central dans le voisinage, puis ajoute les gradients pour déterminer la relation entre le niveau de gris du pixel central et les niveaux de gris des autres pixels du voisinage, et enfin par l'opération de gradient En conséquence, l'échelle de gris des pixels est ajustée.

G_4 = \ begin {bmatrix} 0 & 1 & 0 \\ 1 & -4 & 1 \\ 0 & 1 & 0 \ end {bmatrix}   G_8 = \ begin {bmatrix} 1 & 1 & 1 \\ 1 & -8 & 1 \\ 1 & 1 & 1 \ end {bmatrix}

Le processus de base de l'opérateur laplacien consiste à déterminer la valeur de gris du pixel central de l'image et les valeurs de gris des autres pixels qui l'entourent. Si le gris du pixel central est plus élevé, alors le gris du pixel central est augmenté; sinon, le gris du pixel central est réduit. Afin de réaliser l'opération de netteté de l'image. Dans le processus de mise en œuvre de l'algorithme, l'opérateur laplacien calcule les gradients dans les quatre ou huit directions du pixel central dans le voisinage, puis ajoute les gradients pour déterminer la relation entre le niveau de gris du pixel central et les niveaux de gris des autres pixels du voisinage, et enfin par l'opération de gradient En conséquence, l'échelle de gris des pixels est ajustée.

         L'opérateur de Laplace est un opérateur isotrope, opérateur différentiel du second ordre, avec invariance de rotation. Il est plus approprié lorsque vous ne vous souciez que de la position du bord sans tenir compte de la différence de niveaux de gris des pixels environnants. La réponse de l'opérateur de Laplace aux pixels isolés est plus forte que la réponse aux bords ou aux lignes, elle ne convient donc qu'aux images sans bruit. En présence de bruit, un filtrage passe-bas est nécessaire avant la détection des bords à l'aide de l'opérateur laplacien. Par conséquent, l'algorithme de segmentation habituel combine l'opérateur laplacien et l'opérateur de lissage pour générer un nouveau modèle.

LOG (Laplacien de Gaussien)

L'opérateur LOG effectue d'abord un filtrage gaussien sur l'image, puis trouve sa deuxième dérivée laplacienne et détecte la limite de l'image en fonction du point zéro du pot de la deuxième dérivée, c'est-à-dire en détectant les passages par zéro du résultat filtré. Pour obtenir le bord de l'image ou de l'objet.

  L'opérateur LOG considère de manière exhaustive les deux directions de la suppression du bruit et de la détection des contours, et combine le filtre de lissage Gauss et le filtre d'accentuation laplacien pour lisser d'abord le bruit, puis effectuer la détection des contours, de sorte que l'effet sera meilleur. . Cet opérateur est similaire au modèle mathématique en physiologie visuelle, il a donc été largement utilisé dans le domaine du traitement d'image. Il a une forte capacité anti-interférence, une précision de positionnement des limites élevée, une bonne continuité des bords et peut extraire efficacement les limites avec un faible contraste.

Introduction à l'API

Remplissez les bords

copyMakeBorder(src,dst,top,bottom,left,right,borderType,color)
// src 原图   dst 目标图
// top,bottom,left,right 上下左右填充宽度
//borderType 填充类型 
//color 当使用BORDERTPYPE_CONSTANTP时,才用

Opérateur Sobel (Scharr)

Sobel(  //Scharr相同
InputArray Src,   //输入图像
QutputArray dst,  //输出图像
int depth,        //输出位深度 设为"-1"会自适应 选择合适的
int dx,    //x方向,几阶导数
int dy,    //y方向,几阶导数      
int ksize,        //kernel大小,必须是奇数
double scale = 1, //输出是否缩放,即乘因子
double delta = 0, //输出是否加偏差,即加因子
int borderType = BORDER_DEFAULT  //
)

Laplacien 算 子

Laplacian( 
src_gray,     //src_gray: 输入图像
dst,          //dst: 输出图像
ddepth,       //ddepth: 输出图像的深度因为输入图像的深度是 CV_8U ,这里我们必须定义 ddepth = CV_16S 以避免外溢。
kernel_size,  //kernel_size: 内部调用的 Sobel算子的内核大小,此例中设置为3。
scale, 
delta, 
BORDER_DEFAULT 
);

Pratique du code

Supplément Edge

#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
	//src = imread("src.jpg");
	Mat src = imread("cat.png"),dst;
	if (!src.data)
	{
		cout << "cannot open image" << endl;
		return -1;
	}
	namedWindow("input image", WINDOW_AUTOSIZE);
	imshow("input image", src);
	Mat d1, d2, d3, d4,d5,d6,d7,d8;
	int top = (int)(0.10 * src.rows);
	int bottom = (int)(0.10 * src.rows);
	int left = (int)(0.10 * src.cols);
	int right = (int)(0.10 * src.cols);

	copyMakeBorder(src, d1, top, bottom, left, right, BORDER_CONSTANT, Scalar(255, 255, 255));
	copyMakeBorder(src, d2, top, bottom, left, right, BORDER_DEFAULT);
	copyMakeBorder(src, d3, top, bottom, left, right, BORDER_REFLECT);
	copyMakeBorder(src, d4, top, bottom, left, right, BORDER_REPLICATE);
	copyMakeBorder(src, d5, top, bottom, left, right, BORDER_WRAP);
	copyMakeBorder(src, d6, top, bottom, left, right, BORDER_ISOLATED);
	copyMakeBorder(src, d7, top, bottom, left, right, BORDER_REFLECT101);

	imshow("BORDER_CONSTANT", d1);
	imshow("BORDER_DEFAULT", d2);
	imshow("BORDER_REFLECT", d3);
	imshow("BORDER_REPLICATE", d4);
	imshow("BORDER_WRAP", d5);
	imshow("BORDER_ISOLATED", d6);
	imshow("BORDER_REFLECT101", d7);

	waitKey(0);
	return 0;
}

Bord d'extraction de l'opérateur

#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
	//src = imread("src.jpg");
	Mat src = imread("src.jpg"),gray_src;
	if (!src.data)
	{
		cout << "cannot open image" << endl;
		return -1;
	}
	namedWindow("input image", WINDOW_AUTOSIZE);
	imshow("input image", src);
	GaussianBlur(src, src, Size(3, 3), 0, 0);
	cvtColor(src,src,COLOR_BGR2GRAY);

	//Robert算子
	//X
	Mat dst_rx, dst_ry;
	Mat kernel_x1 = (Mat_<int>(2, 2) << 1, 0, 0, -1);
	filter2D(src, dst_rx, -1, kernel_x1, Point(-1, -1), 0.0);
	
	//Y
	Mat kernel_y1 = (Mat_<int>(2, 2) << 0 ,1, -1, 0);
	filter2D(src, dst_ry, -1, kernel_y1, Point(-1, -1), 0.0);

	//拼接两个方向的梯度
	Mat xygrad = Mat(src.size(), src.type());
	int width = xygrad.cols;
	int height = xygrad.rows;
	for (int row = 0; row < height; row++)
	{
		for (int col = 0; col < width; col++)
		{
			int xg = dst_rx.at<uchar>(row, col);
			int yg = dst_ry.at<uchar>(row, col);
			int xy = xg + yg;
			xygrad.at<uchar>(row, col) = saturate_cast<uchar>(xy);
		}
	}
	imshow("Rebort", xygrad);


	// prewitt算子
	Mat dst_sx, dst_sy;
	//X
	Mat kernel_x2 = (Mat_<int>(3, 3) << -1, 0, 1, -1, 0, 1, -1, 0, 1);
	filter2D(src, dst_sx, -1, kernel_x2, Point(-1, -1), 0.0);
	
	//Y
	Mat kernel_y2 = (Mat_<int>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);
	filter2D(src, dst_sy, -1, kernel_y2, Point(-1, -1), 0.0);
	
	for (int row = 0; row < height; row++)
	{
		for (int col = 0; col < width; col++)
		{
			int xg = dst_sx.at<uchar>(row, col);
			int yg = dst_sy.at<uchar>(row, col);
			int xy = xg + yg;
			xygrad.at<uchar>(row, col) = saturate_cast<uchar>(xy);
		}
	}
	imshow("Prewitt", xygrad);

	//Sobel 算子
	Sobel(src, dst_rx, CV_16S, 1, 0, 3);
	convertScaleAbs(dst_rx, dst_rx);
	Sobel(src, dst_ry, CV_16S, 0, 1, 3);
	convertScaleAbs(dst_ry, dst_ry);
	for (int row = 0; row < height; row++)
	{
		for (int col = 0; col < width; col++)
		{
			int xg = dst_rx.at<uchar>(row, col);
			int yg = dst_ry.at<uchar>(row, col);
			int xy = xg + yg;
			xygrad.at<uchar>(row, col) = saturate_cast<uchar>(xy);
		}
	}
	imshow("Sobel", xygrad);

	//Scharr 算子
	Scharr(src, dst_rx, CV_16S, 1, 0);
	convertScaleAbs(dst_rx, dst_rx);
	Scharr(src, dst_ry, CV_16S, 0, 1);
	convertScaleAbs(dst_ry, dst_ry);
	for (int row = 0; row < height; row++)
	{
		for (int col = 0; col < width; col++)
		{
			int xg = dst_rx.at<uchar>(row, col);
			int yg = dst_ry.at<uchar>(row, col);
			int xy = xg + yg;
			xygrad.at<uchar>(row, col) = saturate_cast<uchar>(xy);
		}
	}
	imshow("Scharr", xygrad);

	//Laplacian 算子
	Mat edge_image;
	Laplacian(src, edge_image, CV_16S, 3);
	convertScaleAbs(edge_image, edge_image);
	imshow("Laplacian", edge_image);
	

	waitKey(0);
	return 0;
}

 

Je suppose que tu aimes

Origine blog.csdn.net/fan1102958151/article/details/107343870
conseillé
Classement