图像预处理——边界检测
来源:互联网 发布:gson map to json 编辑:程序博客网 时间:2024/05/17 23:03
图像的边缘定义为两个强度明显不同的区域之间的过渡,图像的梯度函数即图像灰度变化的速率将在这些过渡边界上存在最大值。如果一个点位于边缘点上,那么它的灰度值会出现阶跃性的变化,对应于一阶导数的极值点、二阶导数的过零点,如图所示。
由图可知,一阶导数的极值点与二阶导数的过零点可用来检测边缘。另外,一阶导数与二阶导数对噪声非常敏感,尤其是二阶导数。因此,在进行边缘检测之前,需充分考虑图像的平滑,以减少噪声的影响。
1)一阶微分边缘检测
图像灰度函数
2)二阶微分边缘检测
通过找图像灰度二阶导数的零交叉点可以确定边缘。图像灰度函数f(x,y)在点f(x,y)在点(x,y)的二阶微分为
式中,由二阶导数的定义可得拉普拉斯算子为
在离散区域中,对连续的拉普拉斯算子最简单的近似运算是计算斜面沿每一个轴线的差值:
该四邻域的拉普拉斯算子可以通过卷积来生成:
式中
增益标准化的四邻域拉普拉斯算子脉冲响应的定义式为
#include "opencv2/opencv.hpp"#include <iostream>using namespace std;using namespace cv;void Gaussian(const Mat &inputImg, Mat &outputImg, double sigma) { //计算窗口大小 int windows = ((int)(6 * sigma - 1)) / 2 * 2 + 1; double *value = new double[windows]; double sum = 0; //计算卷积核 int left = -windows / 2, right = windows / 2 + 1, border = windows / 2; for (int i = left; i < right; i++){ value[i + border] = pow(2.718, -(i * i) / (2 * sigma * sigma)) / (sqrt(2 * 3.1415926) * sigma); sum += value[i + border]; } for (int i = left; i < right; i++){ value[i + border] = value[i + border] / sum; cout << value[i + border] << endl; } //存储中间结果图像 Mat tempImg(inputImg.rows + border * 2, inputImg.cols + border * 2, CV_8UC1); //填充图像 Mat fillImg(inputImg.rows + border * 2, inputImg.cols + border * 2, CV_8UC1); for (int i = border; i < inputImg.rows + border; i++) { for (int j = border; j < inputImg.cols + border; j++) { fillImg.at<uchar>(i, j) = inputImg.at<uchar>((i-border) % (inputImg.rows - 1),(j-border) % (inputImg.cols - 1)); } } //填充图像上方 for (int i = 0; i < border; i++) { for (int j = 0; j < inputImg.cols + border * 2; j++) { fillImg.at<uchar>(i%fillImg.rows, j%fillImg.cols) = inputImg.at<uchar>(i%(inputImg.rows-1), j%(inputImg.cols-1)); } } //填充图像下放 for (int i = inputImg.rows+border; i < inputImg.rows + border * 2; i++) { for (int j = 0; j < inputImg.cols + border * 2; j++) { fillImg.at<uchar>(i%fillImg.rows, j%fillImg.cols) = inputImg.at<uchar>((i-border*2) % (inputImg.rows - 1), j % (inputImg.cols - 1)); } } //填充左方 for (int i = border; i < inputImg.rows + border; i++) { for (int j = 0; j < border; j++) { fillImg.at<Vec3b>(i%fillImg.rows, j%fillImg.cols)[0] = inputImg.at<Vec3b>((i-border) % (inputImg.rows - 1), j % (inputImg.cols - 1))[0]; fillImg.at<Vec3b>(i%fillImg.rows, j%fillImg.cols)[1] = inputImg.at<Vec3b>((i - border) % (inputImg.rows - 1), j % (inputImg.cols - 1))[1]; fillImg.at<Vec3b>(i%fillImg.rows, j%fillImg.cols)[2] = inputImg.at<Vec3b>((i - border) % (inputImg.rows - 1), j % (inputImg.cols - 1))[2]; } } //填充右方 for (int i = border; i < inputImg.rows + border; i++) { for (int j = inputImg.cols+border; j < inputImg.cols + border*2; j++) { fillImg.at<uchar>(i%fillImg.rows, j%fillImg.cols)= inputImg.at<uchar>((i - border) % (inputImg.rows - 1), (j-border*2) % (inputImg.cols - 1)); } } namedWindow("填充后", WINDOW_AUTOSIZE); imshow("填充后", fillImg); //对每行进行一维高斯滤波 for (int i = 0; i < tempImg.rows; i++){ for (int j = border; j < tempImg.cols - border; j++){ tempImg.at<uchar>(i, j)= 0; for (int k = left; k < right; k++){ tempImg.at<uchar>(i, j) += (fillImg.at<uchar>(i, j + k) * value[k + border]); } } } //对结果的每列进行一维高斯滤波 for (int i = 0; i < outputImg.rows; i++){ for (int j = 0; j < outputImg.cols; j++){ outputImg.at<uchar>(i, j) = 0; for (int k = left; k < right; k++){ outputImg.at<uchar>(i, j) += (tempImg.at<uchar>(i + k+border, j+border) * value[k + border]); } } } namedWindow("高斯滤波", WINDOW_AUTOSIZE); imshow("高斯滤波", outputImg);}int main(int argc, char** argv){ Mat pic=imread("d:\\test1.jpg",0); imshow("testpic", pic); int lap[3] = { -1, 4, 1 }; Mat outGaussian(pic.rows, pic.cols, CV_8UC1); Mat out(pic.rows, pic.cols, CV_8UC1); Mat temp(pic.rows, pic.cols, CV_8UC1); for (int i = 0; i < pic.rows; i++){ for (int j = 0; j < pic.cols; j++){ outGaussian.at<uchar>(i, j) = pic.at<uchar>(i, j); out.at<uchar>(i, j) = pic.at<uchar>(i, j); } } for (int i = 1; i < pic.rows - 1; i++){ for (int j = 1; j < pic.cols - 1; j++){ out.at<uchar>(i, j) = (pic.at<uchar>(i, j) * 4 - pic.at<uchar>(i - 1, j) - pic.at<uchar>(i + 1, j) - pic.at<uchar>(i, j - 1) - pic.at<uchar>(i, j + 1)) / 4; } } Gaussian(pic, temp,2); for (int i = 1; i < pic.rows-1; i++){ for (int j = 1; j < pic.cols-1; j++){ outGaussian.at<uchar>(i, j) = (temp.at<uchar>(i, j) * 4 - temp.at<uchar>(i - 1, j) - temp.at<uchar>(i + 1, j) - temp.at<uchar>(i, j - 1) - temp.at<uchar>(i, j + 1)) / 4; } } imshow("out", out); imshow("outGaussian", outGaussian); waitKey(); return 0;}
1 0
- 图像预处理——边界检测
- 图像预处理——边界跟踪、图像分割
- 基于OpenCV的火焰检测(一)——图像预处理
- 基于OpenCV的火焰检测(一)——图像预处理
- 图像预处理——滤波
- 图像预处理——形态学
- Sobel图像边界检测算法实现
- 图像预处理——图像梯度化
- 图像预处理——图像坐标变换
- 图像预处理——图像分割
- opencv——扩充图像边界
- opencv:扩充图像边界—copyMakeBorder()函数
- imgproc模块—图像添加边界
- Python-OpenCV 处理图像:图像中边界和轮廓检测
- 虹膜图像预处理-运动模糊检测
- 图像预处理——对数变换
- 图像预处理——二值化(大律法)
- 图像预处理——自适应二值化
- 并查集——分身法
- 实用的 集合工具类 和 String工具类
- 黑白夜间切换
- selenium版本下载
- 怎么在微信上实现瑜伽在线预约功能
- 图像预处理——边界检测
- UML——初识
- 167. Two Sum II
- 第21章 信号频谱分析
- Activity生命周期笔记
- 【Android】超级手电筒项目总结(上)
- IntelliJ Idea 常用快捷键
- 利用URLConnection来发送POST和GET请求
- mybatis的配置一