时间为友,记录点滴。

我们已经了解过了梯度(一阶微分)的作用,那么为什么要引入二阶微分呢?二阶微分的作用是什么?

还是看图说话:

很明显,一阶微分已经可以把轮廓辨识出来,但是,对于变化较缓的地方,一阶微分会给出一个比较长的序列,对应到图像上就是轮廓比较“粗”, 二阶微分只识别跳变的边缘,对应到图像上就是比较“细”。而且对像素的陡变的地方,二阶微分会出现有“零交叉”的两个点,这种点对边缘定位非常有作用。

所以,在细节增强方面,二阶微分要比一阶微分好的多。

怎么实现二阶微分?

我在《数字图像处理》中已经介绍了拉普拉斯算子, 简单的说就是对上一章的梯度再做一次梯度:

拉普拉斯在就为我们定义了二阶微分形式,所以我们就直接把它拓展到二维图像

上:

因为任意阶微分都是线性操作,所以拉普拉斯变换也是一个线性算子。为了离散地表达这个共识,我们套用上一章的一个公式变换:

X方向:

Y方向:

综合一下:

有了公式,就容易得到基于拉普拉斯算子的模板:

因为拉普拉斯是一种二阶微分算子,因此其强调的是图像中灰度的突变,并不强调图像的缓慢变换区域。这样一些渐变的浅灰色边线就会变成图片轮廓的背景色。如果我们想要保持原图像并且看到增强的边缘图像,可以把原图和拉普拉斯图像简单叠加。

套用以下公式:

为原图

为拉普拉斯处理后的图像

为处理的系数

为最终保持原图像并且增强边缘的图像

好了,有了上面理论做指导,我们实现一下,看看效果。

在OpenCV中,有现成的API可以给我们使用:

CV_EXPORTS_W void Laplacian( InputArray src, OutputArray dst, int ddepth,

int ksize = 1, double scale = 1, double delta = 0,

int borderType = BORDER_DEFAULT );src_gray,输入图像

dst,Laplace操作结果

ddepth,输出图像深度,因为输入图像一般为CV_8U,为了避免数据溢出,输出图像深度应该设置为CV_16S或者更高

kernel_size,filter mask的规模,我们的mask时3x3的,所以这里应该设置为3

scale,delta,BORDER_DEFAULT,默认设置就好

C++:

注意点:1. 因为拉普拉斯是二阶微分,对噪点非常敏感,所以在做锐化之前可以用kernelSize=3的高斯滤波先。

2. 不知道为什么,做出来的拉普拉斯噪声值比较大。

#include #include #include

using namespace std;

using namespace cv;

static bool laplaceTest(Mat imgOri, bool needResize = false, bool needBlur = false);

static void showImgPara(Mat &img);

int main()

{

Mat imgOri = imread("Fig0338(a)(blurry_moon).tif");

laplaceTest(imgOri);

Mat imgGril = imread("Gril.jpg");

//laplaceTest(imgGril, true, false);

waitKey(0);

return true;

}

static bool laplaceTest(Mat imgOri, bool needResize, bool needBlur)

{

Mat imgLaplace, imgLaplaceDelta, imgLaplaceAdd1;

float fx = 0, fy = 0;

showImgPara(imgOri);

imshow("laplaceTest imgOri", imgOri);

if (needBlur)

{

GaussianBlur(imgOri, imgOri, Size(7, 7), 0, 0);

}

if (needResize)

{

resize(imgOri, imgOri, Size(imgOri.cols * 0.5, imgOri.rows * 0.5), fx = 0, fy = 0, INTER_LINEAR);

}

if (1 != imgOri.channels())

{

cvtColor(imgOri, imgOri, COLOR_BGR2GRAY);

}

// Laplace without deltaLaplacian(imgOri, imgLaplace, CV_16S, 3, 1, 0);

convertScaleAbs(imgLaplace, imgLaplace);

imshow("laplaceTest imgLaplace", imgLaplace);

// Laplace with deltaLaplacian(imgOri, imgLaplaceDelta, CV_16S, 3, 1, 100);

convertScaleAbs(imgLaplaceDelta, imgLaplaceDelta);

imshow("laplaceTest imgLaplaceDelta", imgLaplaceDelta);

// Laplace add originaladdWeighted(imgOri, 1.0, imgLaplace, -1.0, 0.0, imgLaplaceAdd1, CV_32F);

convertScaleAbs(imgLaplaceAdd1, imgLaplaceAdd1);

imshow("laplaceTest imgLaplaceAdd1", imgLaplaceAdd1);

return true;

}

static void showImgPara(Mat &img)

{

cout << "sizeof(img) is: " << sizeof(img) << ", img size is: " << img.size << endl;

cout << "rows x cols: (" << img.rows << " x " << img.cols << ")" << endl;

cout << "dims: " << img.dims << endl;

cout << "channels: " << img.channels() << endl;

cout << "type: " << img.type() << endl;

cout << "depth:" << img.depth() << endl;

cout << "elemSize:" << img.elemSize() << " (Bytes per element)" << endl;

cout << "elemSize1:" << img.elemSize1() << "(Bytes per channel)" << endl;

cout << "step[0]: " << img.step[0] << " (Bytes per cows only when 2 dims)" << endl;

cout << "step[1]: " << img.step[1] << " (Bytes per element only when 2 dims)" << endl;

cout << "step1(0): " << img.step1(0) << ", step1(1): " << img.step1(1) << " (step / elemSize1)" << endl;

cout << "----- showImgPara End ----\n" << endl;

}

运行结果:

Python:

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# author:lowkeyway time:8/24/2019

import sys

import cv2 as cv

import numpy as np

def laplaceTest(imgOri, needResize = False, needBlur = False):

cv.imshow("imgOri", imgOri)

if len(imgOri.shape) is not 2:

imgOri = cv.cvtColor(imgOri, cv.COLOR_BGR2GRAY)

if needResize:

imgOri = cv.resize(imgOri, (int(imgOri.shape[1]*0.5), int(imgOri.shape[0]*0.5)))

if needBlur:

imgOri = cv.GaussianBlur(imgOri, (3, 3), 1)

# Laplace only

imgLap = cv.Laplacian(imgOri, cv.CV_16S)

imgLap = cv.convertScaleAbs(imgLap)

cv.imshow("imglap", imgLap)

# Laplace Delta

imgLapDelta = cv.Laplacian(imgOri, cv.CV_16S, delta=100)

imgLapDelta = cv.convertScaleAbs(imgLapDelta)

cv.imshow("imgLapDelta", imgLapDelta)

# Laplace Add

imgLapAdd = cv.addWeighted(imgOri, 1.0, imgLap, -1.0, 0, dtype=cv.CV_32F)

imgLapAdd = cv.convertScaleAbs(imgLapAdd)

cv.imshow("imgLapAdd", imgLapAdd)

def main_func(argv):

imgMoon = cv.imread("Fig0338(a)(blurry_moon).tif")

# laplaceTest(imgMoon)

imgGril = cv.imread("Gril.jpg")

laplaceTest(imgGril, True, True)

cv.waitKey(0)

if __name__ == '__main__':

main_func(sys.argv)

python 拉普拉斯锐化_(二十四)用二阶微分(拉普拉斯算子)实现图像锐化相关推荐

  1. python+OpenCV笔记(二十四):Shi-Tomasi角点检测

    Shi-Tomasi角点检测 原理 python+OpenCV笔记(二十二):角点检测原理(Harris角点检测原理.Shi-Tomasi角点检测原理)https://blog.csdn.net/qq ...

  2. 【python数据挖掘课程】二十四.KMeans文本聚类分析互动百科语料

    这是<Python数据挖掘课程>系列文章,也是我上课内容及书籍中的一个案例.本文主要讲述文本聚类相关知识,包括中文分词.数据清洗.特征提取.TF-IDF.KMeans聚类等步骤.本篇文章为 ...

  3. pandas 更改单元格的值_懂Excel轻松入门Python数据分析包pandas(二十四):连续区域...

    此系列文章收录在公众号中:数据大宇宙 > 数据处理 >E-pd 转发本文并私信我"python",即可获得Python资料以及更多系列文章(持续更新的) 经常听别人说 ...

  4. python学习笔记分享(二十四)python学习笔记分期补充(二)复数,randint与sample,进制转换表,转义字符,二维数组,键,end,pass,迭代器和生成器

    一:复数 Python支持复数,复数由实数部分和虚数部分构成,可以用a + bj,或者complex(a,b)表示, 复数的实部a和虚部b都是浮点型. complex(x) 将x转换到一个复数,实数部 ...

  5. python接口自动化(二十四)--unittest断言——中(详解)

    简介 上一篇通过简单的案例给小伙伴们介绍了一下unittest断言,这篇我们将通过结合和围绕实际的工作来进行unittest的断言.这里以获取城市天气预报的接口为例,设计了 2 个用例,一个是查询北京 ...

  6. python生成器迭代_二十、深入Python迭代器和生成器

    「@Author:Runsen」 学习python的过程中,迭代器与生成器是绕不开的话题, 什么是迭代器和生成器呢? 下面我们来了解一下什么是迭代.但在了解迭代器之前,首先需要知道什么是容器. 容器 ...

  7. 第四单元 用python学习微积分(二十四)三角函数的积分以及三角替换

    本文内容来自于学习麻省理工学院公开课:单变量微积分-三角函数的积分及三角替换-网易公开课 开发环境准备:CSDN 目录 一.三角学中的基本知识 1.三角学公式: (1) ​倍角公式 (2) ​ 半角公 ...

  8. Python之爬虫(二十四) 爬虫与反爬虫大战

    爬虫与发爬虫的厮杀,一方为了拿到数据,一方为了防止爬虫拿到数据,谁是最后的赢家? 重新理解爬虫中的一些概念 爬虫:自动获取网站数据的程序 反爬虫:使用技术手段防止爬虫程序爬取数据 误伤:反爬虫技术将普 ...

  9. Python遥感图像处理应用篇(二十四):Python绘制遥感图像各波段热力图(相关系数矩阵)

    给多光谱遥感图像各个波段绘制热力图,首先需要计算波段之间的相关系数矩阵,而计算遥感图像波段相关系数矩阵有不同的方法,常用的我们可以采用遥感图像处理软件计算,比如ENVI软件就可以计算相关系数矩阵,使用 ...

  10. python 分数序列求和公式_Python分数序列求和,编程练习题实例二十四

    本文是关于Python分数序列求和的应用练习,适合菜鸟练习使用,python大牛绕行哦. Python练习题问题如下: 问题简述:有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13 要 ...

最新文章

  1. python100个免费实例-Python实例100个(基于最新Python3.7版本)
  2. 042_JDK的Map接口
  3. 用计算机计算板书,用计算器计算教案板书设计
  4. spring兼容mysql_springboot 最新版本支持 mysql6.0.6吗
  5. 基于预训练语言模型的文本生成研究综述
  6. leetcode Largest Rectangle in Histogram 单调栈
  7. 省二级计算机考试VB题库,2015河南省全国计算机等级考试二级笔试试卷VB考试题库...
  8. python 包之 Pygame 游戏开发教程
  9. 备件管理系统c语言,图书管理系统的设计与开发及体育用品库存管理系统设计.doc...
  10. Allegrocadence PCB测量时显示两种单位(mil mm)
  11. Win10专业版如何安装Docker
  12. 网易公开课计算机原理,网易公开课给大一新生“量身订做”精品课程
  13. request 和 response 对象的具体介绍
  14. C语言取模运算符的妙用
  15. RealsenseD415/D435深度相机常用资料汇总
  16. Spring Autowire自动装配 ---残梦追月原创
  17. LOJ #573. 「LibreOJ NOI Round #2」单枪匹马 线段树
  18. 深度解析—汽车“以租代购”究竟是怎么回事?
  19. 06_多窗口文档编辑器(小钱版)[Qt开发][2012-03-07]
  20. tiktok x-tt-params

热门文章

  1. ISO质量管理体系认证有哪些流程?
  2. 计算机中的ip地址是什么 ???
  3. xilinx fpga SEM
  4. R树:处理空间存储问题
  5. 数据库SQL---SQL语言的功能
  6. 用c语言做自动售货机程序,C语言实现查询自动售货机中的商品价格【实例分享】...
  7. python报错“cannot import name ft2font”
  8. 10强出炉 | 香港科大-杰瑞集团 2022【人工智能】百万奖金国际创业大赛半决赛成功举办...
  9. system76_您需要了解有关System76的开源固件项目的知识
  10. latex 甘特图_Markdown语法图文全面详解(10分钟学会)