python 拉普拉斯锐化_(二十四)用二阶微分(拉普拉斯算子)实现图像锐化
时间为友,记录点滴。
我们已经了解过了梯度(一阶微分)的作用,那么为什么要引入二阶微分呢?二阶微分的作用是什么?
还是看图说话:
很明显,一阶微分已经可以把轮廓辨识出来,但是,对于变化较缓的地方,一阶微分会给出一个比较长的序列,对应到图像上就是轮廓比较“粗”, 二阶微分只识别跳变的边缘,对应到图像上就是比较“细”。而且对像素的陡变的地方,二阶微分会出现有“零交叉”的两个点,这种点对边缘定位非常有作用。
所以,在细节增强方面,二阶微分要比一阶微分好的多。
怎么实现二阶微分?
我在《数字图像处理》中已经介绍了拉普拉斯算子, 简单的说就是对上一章的梯度再做一次梯度:
拉普拉斯在就为我们定义了二阶微分形式,所以我们就直接把它拓展到二维图像
上:
因为任意阶微分都是线性操作,所以拉普拉斯变换也是一个线性算子。为了离散地表达这个共识,我们套用上一章的一个公式变换:
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 拉普拉斯锐化_(二十四)用二阶微分(拉普拉斯算子)实现图像锐化相关推荐
- python+OpenCV笔记(二十四):Shi-Tomasi角点检测
Shi-Tomasi角点检测 原理 python+OpenCV笔记(二十二):角点检测原理(Harris角点检测原理.Shi-Tomasi角点检测原理)https://blog.csdn.net/qq ...
- 【python数据挖掘课程】二十四.KMeans文本聚类分析互动百科语料
这是<Python数据挖掘课程>系列文章,也是我上课内容及书籍中的一个案例.本文主要讲述文本聚类相关知识,包括中文分词.数据清洗.特征提取.TF-IDF.KMeans聚类等步骤.本篇文章为 ...
- pandas 更改单元格的值_懂Excel轻松入门Python数据分析包pandas(二十四):连续区域...
此系列文章收录在公众号中:数据大宇宙 > 数据处理 >E-pd 转发本文并私信我"python",即可获得Python资料以及更多系列文章(持续更新的) 经常听别人说 ...
- python学习笔记分享(二十四)python学习笔记分期补充(二)复数,randint与sample,进制转换表,转义字符,二维数组,键,end,pass,迭代器和生成器
一:复数 Python支持复数,复数由实数部分和虚数部分构成,可以用a + bj,或者complex(a,b)表示, 复数的实部a和虚部b都是浮点型. complex(x) 将x转换到一个复数,实数部 ...
- python接口自动化(二十四)--unittest断言——中(详解)
简介 上一篇通过简单的案例给小伙伴们介绍了一下unittest断言,这篇我们将通过结合和围绕实际的工作来进行unittest的断言.这里以获取城市天气预报的接口为例,设计了 2 个用例,一个是查询北京 ...
- python生成器迭代_二十、深入Python迭代器和生成器
「@Author:Runsen」 学习python的过程中,迭代器与生成器是绕不开的话题, 什么是迭代器和生成器呢? 下面我们来了解一下什么是迭代.但在了解迭代器之前,首先需要知道什么是容器. 容器 ...
- 第四单元 用python学习微积分(二十四)三角函数的积分以及三角替换
本文内容来自于学习麻省理工学院公开课:单变量微积分-三角函数的积分及三角替换-网易公开课 开发环境准备:CSDN 目录 一.三角学中的基本知识 1.三角学公式: (1) 倍角公式 (2) 半角公 ...
- Python之爬虫(二十四) 爬虫与反爬虫大战
爬虫与发爬虫的厮杀,一方为了拿到数据,一方为了防止爬虫拿到数据,谁是最后的赢家? 重新理解爬虫中的一些概念 爬虫:自动获取网站数据的程序 反爬虫:使用技术手段防止爬虫程序爬取数据 误伤:反爬虫技术将普 ...
- Python遥感图像处理应用篇(二十四):Python绘制遥感图像各波段热力图(相关系数矩阵)
给多光谱遥感图像各个波段绘制热力图,首先需要计算波段之间的相关系数矩阵,而计算遥感图像波段相关系数矩阵有不同的方法,常用的我们可以采用遥感图像处理软件计算,比如ENVI软件就可以计算相关系数矩阵,使用 ...
- python 分数序列求和公式_Python分数序列求和,编程练习题实例二十四
本文是关于Python分数序列求和的应用练习,适合菜鸟练习使用,python大牛绕行哦. Python练习题问题如下: 问题简述:有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13 要 ...
最新文章
- python100个免费实例-Python实例100个(基于最新Python3.7版本)
- 042_JDK的Map接口
- 用计算机计算板书,用计算器计算教案板书设计
- spring兼容mysql_springboot 最新版本支持 mysql6.0.6吗
- 基于预训练语言模型的文本生成研究综述
- leetcode Largest Rectangle in Histogram 单调栈
- 省二级计算机考试VB题库,2015河南省全国计算机等级考试二级笔试试卷VB考试题库...
- python 包之 Pygame 游戏开发教程
- 备件管理系统c语言,图书管理系统的设计与开发及体育用品库存管理系统设计.doc...
- Allegrocadence PCB测量时显示两种单位(mil mm)
- Win10专业版如何安装Docker
- 网易公开课计算机原理,网易公开课给大一新生“量身订做”精品课程
- request 和 response 对象的具体介绍
- C语言取模运算符的妙用
- RealsenseD415/D435深度相机常用资料汇总
- Spring Autowire自动装配 ---残梦追月原创
- LOJ #573. 「LibreOJ NOI Round #2」单枪匹马 线段树
- 深度解析—汽车“以租代购”究竟是怎么回事?
- 06_多窗口文档编辑器(小钱版)[Qt开发][2012-03-07]
- tiktok x-tt-params
热门文章
- ISO质量管理体系认证有哪些流程?
- 计算机中的ip地址是什么 ???
- xilinx fpga SEM
- R树:处理空间存储问题
- 数据库SQL---SQL语言的功能
- 用c语言做自动售货机程序,C语言实现查询自动售货机中的商品价格【实例分享】...
- python报错“cannot import name ft2font”
- 10强出炉 | 香港科大-杰瑞集团 2022【人工智能】百万奖金国际创业大赛半决赛成功举办...
- system76_您需要了解有关System76的开源固件项目的知识
- latex 甘特图_Markdown语法图文全面详解(10分钟学会)