写在前面 :本博客仅作记录学习之用,部分图片来自网络,如需使用请注明出处,同时如有侵犯您的权益,请联系删除!
- 前言
- 小波变换
- 基于cv2的分解与合成
- 基于PIL的分解与合成
- 解析命令行
- 完整代码
- 效果
- 致谢
本博客仅为学习记录之用,目的在于后续若需要相关的有资可查。在言语上恐有诸多纰漏,如有错误,欢迎指出交流学习!
本博客所包含的大致内容: 小波分解原理;基于python-opencv的RGB图像的小波分解与合成;基于PIL的RGB图像的小波分解与合成;解析命令行的简单使用。
小波变换(wavelet transform,WT)继承和发展了短时傅立叶变换局部化的思想,同时又克服了窗口大小不随频率变化等缺点,能够提供一个随频率改变的“时间-频率”窗口,是进行信号时频分析和处理的理想工具。
主要特点:通过变换能够充分突出问题某些方面的特征,能对时间(空间)频率的局部化分析,通过伸缩平移运算对信号(函数)逐步进行多尺度细化,最终达到高频处时间细分,低频处频率细分,能自动适应时频信号分析的要求。小波变换联系了应用数学、物理学、计算机科学、信号与信息处理、图像处理、地震勘探等多个学科。[1]
|
|
|
图1来源:稍有常识的人的知乎
图2来源:维维手作的博客
def harr_cv2(img, gray=False): # cv2
if img.shape[-1] == 3:
if gray:
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
bcA, (bcH, bcV, bcD) = pywt.dwt2(img, "haar")
return bcA, (bcH + bcV + bcD)
else:
(b, g, r) = cv2.split(img)
bcA, (bcH, bcV, bcD) = pywt.dwt2(b, "haar")
gcA, (gcH, gcV, gcD) = pywt.dwt2(g, "haar")
rcA, (rcH, rcV, rcD) = pywt.dwt2(r, "haar")
return (cv2.merge([bcA, gcA, rcA])), (bcV+gcV+rcV+bcH+gcH+rcH+bcD+gcD+rcD)
else:
bcA, (bcH, bcV, bcD) = pywt.dwt2(img, "haar")
return bcA, (bcH+bcV+bcD)
基于PIL的分解与合成
def harr_PIL(img, gray=False, vh=None): # PIL
if img.mode == 'RGB':
if gray:
img = img.convert('L')
bcA, (bcH, bcV, bcD) = pywt.dwt2(img, "haar")
if vh:
return Image.fromarray(bcH).convert('RGB'), Image.fromarray(bcV).convert('RGB')
else:
return Image.fromarray(bcA).convert('RGB'), Image.fromarray((bcH+bcV+bcD)).convert('RGB')
else:
(b, g, r) = img.split()
bcA, (bcH, bcV, bcD) = pywt.dwt2(b, "haar")
gcA, (gcH, gcV, gcD) = pywt.dwt2(g, "haar")
rcA, (rcH, rcV, rcD) = pywt.dwt2(r, "haar")
if vh:
return Image.fromarray(bcH+gcH+rcH).convert('RGB'), Image.fromarray(bcV+gcV+rcV).convert('RGB')
else:
return (Image.merge('RGB', (Image.fromarray(bcA).convert('L'),
Image.fromarray(gcA).convert('L'),
Image.fromarray(rcA).convert('L')))),
Image.fromarray(bcV+gcV+rcV+bcH+gcH+rcH+bcD+gcD+rcD).convert('L')
elif img.mode == 'RGBA':
img = img.convert('RGB')
if gray:
img = img.convert('L')
bcA, (bcH, bcV, bcD) = pywt.dwt2(img, "haar")
if vh:
return Image.fromarray(bcH).convert('RGB'), Image.fromarray(bcV).convert('RGB')
else:
return Image.fromarray(bcA), Image.fromarray((bcH+bcV+bcD))
else:
r, g, b = img.split()
bcA, (bcH, bcV, bcD) = pywt.dwt2(b, "haar")
gcA, (gcH, gcV, gcD) = pywt.dwt2(g, "haar")
rcA, (rcH, rcV, rcD) = pywt.dwt2(r, "haar")
if vh:
return Image.fromarray(bcH+gcH+rcH).convert('RGB'), Image.fromarray(bcV+gcV+rcV).convert('RGB')
else:
return (Image.merge('RGB', (Image.fromarray(bcA).convert('L'),
Image.fromarray(gcA).convert('L'),
Image.fromarray(rcA).convert('L')))),
Image.fromarray(bcV+gcV+rcV+bcH+gcH+rcH+bcD+gcD+rcD).convert('L')
elif img.mode == 'L':
bcA, (bcH, bcV, bcD) = pywt.dwt2(img, "haar")
if vh:
return Image.fromarray(bcH).convert('RGB'), Image.fromarray(bcV).convert('RGB')
else:
return Image.fromarray(bcA), Image.fromarray((bcH+bcV+bcD))
else:
raise ValueError('please check the pic')
解析命令行
def parser_options():
parser = argparse.ArgumentParser(description='haar')#实例化
parser.add_argument('--test_dir', type=bool, default=True, help='TEST DIR path')
parser.add_argument('--pic_path', type=str, default='img/hzgg.jpg', help='if test dir pic path, or the pic path')
parser.add_argument('--mode', type=str, default='cv2', help='cv2 or PIL')
parser.add_argument('--save_path', type=str, default='img/Result', help='save path')
parser.add_argument('--gray', type=bool, default=False, help='gray')
return parser
完整代码
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''
@File :Harr.py
@Author :Xiaodong
@Function:
@Date :2022/4/7 15:25
'''
import pywt
from tqdm import tqdm
import argparse
from PIL import Image
import cv2
import os
def harr_cv2(img, gray=False): # cv2
if img.shape[-1] == 3:
if gray:
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
bcA, (bcH, bcV, bcD) = pywt.dwt2(img, "haar")
return bcA, (bcH + bcV + bcD)
else:
(b, g, r) = cv2.split(img)
bcA, (bcH, bcV, bcD) = pywt.dwt2(b, "haar")
gcA, (gcH, gcV, gcD) = pywt.dwt2(g, "haar")
rcA, (rcH, rcV, rcD) = pywt.dwt2(r, "haar")
return (cv2.merge([bcA, gcA, rcA])), (bcV+gcV+rcV+bcH+gcH+rcH+bcD+gcD+rcD)
else:
bcA, (bcH, bcV, bcD) = pywt.dwt2(img, "haar")
return bcA, (bcH+bcV+bcD)
def harr_PIL(img, gray=False, vh=None): # PIL
if img.mode == 'RGB':
if gray:
img = img.convert('L')
bcA, (bcH, bcV, bcD) = pywt.dwt2(img, "haar")
if vh:
return Image.fromarray(bcH).convert('RGB'), Image.fromarray(bcV).convert('RGB')
else:
return Image.fromarray(bcA).convert('RGB'), Image.fromarray((bcH+bcV+bcD)).convert('RGB')
else:
(b, g, r) = img.split()
bcA, (bcH, bcV, bcD) = pywt.dwt2(b, "haar")
gcA, (gcH, gcV, gcD) = pywt.dwt2(g, "haar")
rcA, (rcH, rcV, rcD) = pywt.dwt2(r, "haar")
if vh:
return Image.fromarray(bcH+gcH+rcH).convert('RGB'), Image.fromarray(bcV+gcV+rcV).convert('RGB')
else:
return (Image.merge('RGB', (Image.fromarray(bcA).convert('L'),
Image.fromarray(gcA).convert('L'),
Image.fromarray(rcA).convert('L')))),
Image.fromarray(bcV+gcV+rcV+bcH+gcH+rcH+bcD+gcD+rcD).convert('L')
elif img.mode == 'RGBA':
img = img.convert('RGB')
if gray:
img = img.convert('L')
bcA, (bcH, bcV, bcD) = pywt.dwt2(img, "haar")
if vh:
return Image.fromarray(bcH).convert('RGB'), Image.fromarray(bcV).convert('RGB')
else:
return Image.fromarray(bcA), Image.fromarray((bcH+bcV+bcD))
else:
r, g, b = img.split()
bcA, (bcH, bcV, bcD) = pywt.dwt2(b, "haar")
gcA, (gcH, gcV, gcD) = pywt.dwt2(g, "haar")
rcA, (rcH, rcV, rcD) = pywt.dwt2(r, "haar")
if vh:
return Image.fromarray(bcH+gcH+rcH).convert('RGB'), Image.fromarray(bcV+gcV+rcV).convert('RGB')
else:
return (Image.merge('RGB', (Image.fromarray(bcA).convert('L'),
Image.fromarray(gcA).convert('L'),
Image.fromarray(rcA).convert('L')))),
Image.fromarray(bcV+gcV+rcV+bcH+gcH+rcH+bcD+gcD+rcD).convert('L')
elif img.mode == 'L':
bcA, (bcH, bcV, bcD) = pywt.dwt2(img, "haar")
if vh:
return Image.fromarray(bcH).convert('RGB'), Image.fromarray(bcV).convert('RGB')
else:
return Image.fromarray(bcA), Image.fromarray((bcH+bcV+bcD))
else:
raise ValueError('please check the pic')
def parser_options():
parser = argparse.ArgumentParser(description='haar')
parser.add_argument('--test_dir', type=bool, default=True, help='TEST DIR path')
parser.add_argument('--pic_path', type=str, default='img/hzgg.jpg', help='if test dir pic path, or the pic path')
parser.add_argument('--mode', type=str, default='cv2', help='cv2 or PIL')
parser.add_argument('--save_path', type=str, default='img/Result', help='save path')
parser.add_argument('--gray', type=bool, default=False, help='gray')
return parser
def main():
parser = parser_options()
args = parser.parse_args()#获得输入参数的信息
if not args.test_dir:
if not os.path.exists(args.save_path):
os.makedirs(args.save_path)
if args.mode == 'cv2':
pic = cv2.imread(args.pic_path)
if pic is None:
pass
low, high = harr_cv2(pic, args.gray)
cv2.imwrite(f'{args.save_path}/low.png', low)
cv2.imwrite(f'{args.save_path}/high.png', high)
elif args.mode == 'PIL':
pic = Image.open(args.pic_path)
low, high = harr_PIL(pic, args.gray)
low.save(f'{args.save_path}/low.png')
high.save(f'{args.save_path}/high.png')
else:
pics = os.listdir(args.pic_path)
if not os.path.exists(args.save_path):
os.makedirs(args.save_path)
if args.mode == 'cv2':
for i, pic in enumerate(tqdm(pics)):
name = pic.split('.')[0]
pic = cv2.imread(os.path.join(args.pic_path, pic))
low, high = harr_cv2(pic, args.gray)
cv2.imwrite(f'{args.save_path}/{name}_low.png', low)
cv2.imwrite(f'{args.save_path}/{name}_high.png', high)
elif args.mode == 'PIL':
for i, pic in enumerate(tqdm(pics)):
name = pic.split('.')[0]
pic = Image.open(os.path.join(args.pic_path, pic))
low, high = harr_PIL(pic, args.gray)
print(pic)
low.save(f"{args.save_path}/{name}_low.png")
high.save(f'{args.save_path}/{name}_high.png')
if __name__ == '__main__':
main()
效果
|
|
|
|
|
|
欲尽善本文,因所视短浅,怎奈所书皆是瞽言蒭议。行文至此,诚向予助与余者致以谢意。


![[学习记录]小波变换分解与恢复 [学习记录]小波变换分解与恢复](http://www.mshxw.com/aiimages/31/844175.png)
