[传统图像处理]-------DOG算子(高斯差分算子)和高斯模糊

一,DOG算子的作用:

DOG(Difference of Gaussian)意为高斯函数的差分。是灰度图像增强和角点检测的一种方法。

二、高斯模糊

由于DOG是利用高斯模糊(也叫高斯平滑)实现的,所以有必要先讲一下高斯模糊是什么:

对于一个图像而言,如果某个像素点跟一个卷积核进行卷积,如下图的,卷积核的尺寸为3x3,且中心点为1,其余为0,则卷积的前后图像是一样的。原因是当前像素点的值,只跟这一点本身有关(且权重为1),跟周边点无关,所以卷积前后都是一样的。

[传统图像处理]-------DOG算子(高斯差分算子)和高斯模糊_第1张图片

那么如果卷积核不是这样的呢?是符合高斯分布的呢?

高斯函数我们都看过,就是呈现中间高,四周低的形状(如下图):

[传统图像处理]-------DOG算子(高斯差分算子)和高斯模糊_第2张图片

在二维的情况下(即图像),二维高斯函数公式如下:

其中σ(sigma)是方差,σ越小高斯函数的峰(中间部分)就越高,σ越大,则峰就越平滑,图像卷积效果也越模糊,更平滑。

所以高斯模糊就是卷积核中的权重跟高斯函数一样,中间高,向四周逐渐趋于平缓。那这样子造成的一个效果就是,当前像素点的值跟四周的值有关系,且越近的点对当前点的贡献就越大,越远的点则贡献越小。所以会起到一个模糊的作用。

高斯模糊代码:

import cv2
import numpy as np
img = cv2.imread('D://fangzi.jpg')
cv2.imshow('img',img)
cv2.resizeWindow('img',640,480)
#img_ = cv2.GaussianBlur(img,ksize=(9,9),sigmaX=0,sigmaY=0)
img_ = cv2.GaussianBlur(img,(9,9),2)
cv2.imshow('img_',img_)
cv2.resizeWindow('img_',640,480)
cv2.waitKey()

效果:

 

三、DOG算子原理:

我们知道高斯模糊后,就开始看看DOG算子了。

DOG是用于角点检测(也叫特征点提取)的。主要流程如下图:

[传统图像处理]-------DOG算子(高斯差分算子)和高斯模糊_第3张图片

左边是原图和三种不同σ的高斯模糊后的图。右边是对高斯滤波后的图片(相邻状态下)依次进行两两相减可得到右边的三个高斯函数的差分图(简称DOG)。

红色标记为当前像素点,黄色对应的像素点表示当前像素点邻接的点,共26(上图中27个黄点减去一个红点)个,如果该点(红点)是所有邻接像素点(黄点)的最大值或最小值,则红色标记对应的点为特征点。

DOG代码:

#include 
#include 

using namespace std;
using namespace cv;

int main()
{
	Mat ori_img = imread("D://lena.png");
	Mat gray_img;
	cvtColor(ori_img, gray_img, CV_RGB2GRAY);
	imshow("gray", gray_img);
	gray_img.convertTo(gray_img, CV_32F);// float -像素是在0-1.0之间的任意值,这对于一些数据集的计算很有用,但是它必须通过将每个像素乘以255来转换成8位来保存或显示。

	Mat gauss1, gauss2;
	GaussianBlur(gray_img, gauss1, Size(5, 5), 0.3, 0.3);
	GaussianBlur(gray_img, gauss2, Size(5, 5), 0.4, 0.4);

	Mat DoG1, DoG2, DoG3;
	DoG1 = gauss1 - gauss2;
	imshow("DOG1", DoG1);
	GaussianBlur(gray_img, gauss1, Size(5, 5), 0.6, 0.6);
	GaussianBlur(gray_img, gauss2, Size(5, 5), 0.7, 0.7);
	DoG2 = gauss1 - gauss2;
	imshow("DOG2", DoG2);
	GaussianBlur(gray_img, gauss1, Size(5, 5), 0.7, 0.7);
	GaussianBlur(gray_img, gauss2, Size(5, 5), 0.8, 0.8);
	DoG3 = gauss1 - gauss2;
	imshow("DOG3", DoG3);
	for (int j = 1; j < gray_img.rows - 1; j++)
	{
		for (int i = 1; i < gray_img.cols - 1; i++)
		{
			if (DoG2.at(j, i) < DoG2.at(j - 1, i - 1) && DoG2.at(j, i) < DoG2.at(j - 1, i) &&
				DoG2.at(j, i) < DoG2.at(j - 1, i + 1) && DoG2.at(j, i) < DoG2.at(j, i - 1) && DoG2.at(j, i) < DoG2.at(j, i + 1) &&
				DoG2.at(j, i) < DoG2.at(j + 1, i - 1) && DoG2.at(j, i) < DoG2.at(j + 1, i) && DoG2.at(j, i) < DoG2.at(j + 1, i + 1)
				&& DoG2.at(j, i) < DoG1.at(j, i) && DoG2.at(j, i) < DoG1.at(j - 1, i - 1) && DoG2.at(j, i) < DoG1.at(j - 1, i) &&
				DoG2.at(j, i) < DoG1.at(j - 1, i + 1) && DoG2.at(j, i) < DoG1.at(j, i - 1) && DoG2.at(j, i) < DoG1.at(j, i + 1) &&
				DoG2.at(j, i) < DoG1.at(j + 1, i - 1) && DoG2.at(j, i) < DoG1.at(j + 1, i) && DoG2.at(j, i) < DoG1.at(j + 1, i + 1)
				&& DoG2.at(j, i) < DoG3.at(j, i) && DoG2.at(j, i) < DoG3.at(j - 1, i - 1) && DoG2.at(j, i) < DoG3.at(j - 1, i) &&
				DoG2.at(j, i) < DoG3.at(j - 1, i + 1) && DoG2.at(j, i) < DoG3.at(j, i - 1) && DoG2.at(j, i) < DoG3.at(j, i + 1) &&
				DoG2.at(j, i) < DoG3.at(j + 1, i - 1) && DoG2.at(j, i) < DoG3.at(j + 1, i) && DoG2.at(j, i) < DoG3.at(j + 1, i + 1))
			{
				//cout << DoG2.at(j, i);
				if (DoG2.at(j, i) < -3)
				{
					circle(ori_img, Point(i, j), 3, CV_RGB(0, 0, 255));
				}
			}
			else
				if (DoG2.at(j, i) > DoG2.at(j - 1, i - 1) && DoG2.at(j, i) > DoG2.at(j - 1, i) &&
					DoG2.at(j, i) > DoG2.at(j - 1, i + 1) && DoG2.at(j, i) > DoG2.at(j, i - 1) && DoG2.at(j, i) > DoG2.at(j, i + 1) &&
					DoG2.at(j, i) > DoG2.at(j + 1, i - 1) && DoG2.at(j, i) > DoG2.at(j + 1, i) && DoG2.at(j, i) > DoG2.at(j + 1, i + 1)
					&& DoG2.at(j, i) > DoG1.at(j, i) && DoG2.at(j, i) > DoG1.at(j - 1, i - 1) && DoG2.at(j, i) > DoG1.at(j - 1, i) &&
					DoG2.at(j, i) > DoG1.at(j - 1, i + 1) && DoG2.at(j, i) > DoG1.at(j, i - 1) && DoG2.at(j, i) > DoG1.at(j, i + 1) &&
					DoG2.at(j, i) > DoG1.at(j + 1, i - 1) && DoG2.at(j, i) > DoG1.at(j + 1, i) && DoG2.at(j, i) > DoG1.at(j + 1, i + 1)
					&& DoG2.at(j, i) > DoG3.at(j, i) && DoG2.at(j, i) > DoG3.at(j - 1, i - 1) && DoG2.at(j, i) > DoG3.at(j - 1, i) &&
					DoG2.at(j, i) > DoG3.at(j - 1, i + 1) && DoG2.at(j, i) > DoG3.at(j, i - 1) && DoG2.at(j, i) > DoG3.at(j, i + 1) &&
					DoG2.at(j, i) > DoG3.at(j + 1, i - 1) && DoG2.at(j, i) > DoG3.at(j + 1, i) && DoG2.at(j, i) > DoG3.at(j + 1, i + 1))
				{
					if (DoG2.at(j, i) > 3)
					{
						circle(ori_img, Point(i, j), 3, CV_RGB(255, 0, 0));
					}
				}
		}
	}
    imshow("result", ori_img);
	waitKey(0);

效果:

输入的灰度图:

[传统图像处理]-------DOG算子(高斯差分算子)和高斯模糊_第4张图片

dog1:

dog2:

dog3:

result:

[传统图像处理]-------DOG算子(高斯差分算子)和高斯模糊_第5张图片

你可能感兴趣的:(图像处理)