通过连接去雾代码遇到一些问题的理解
动机
最近因为自己给自己定的ddl要到了,于是疯狂肝代码。
我主要是做去雾方向,最近因为要用于论文,需要桥梁来和基于语义分割的复杂地貌识别算法相结合。因为深度学习的框架已经基本定在那里了,所以我只好从各种去雾方法的代码上动刀。
源代码
ACE去雾算法(example)
1 | # 线性拉伸处理 |
深度学习predict输入模块
1 | try: |
谈谈想法
import所有def
以ACE算法为例,所使用的方法层层递进,互相嵌套。以方法为单位将所有方法import非常不现实,如果将所有方法放入导包代码之下,又显得深度学习的predict代码不美观也不传统~~(就是看着很不爽)~~。并且假设再增添一种去雾算法,方法会越积越多,但却做不到每个方法都用到,其所谓树大有枯枝。
import os包先运行ACE.py
那我不去改动代码,直接先运行不就完了。想法很美好,现实很骨感。可以通过深度学习输入部分可以看出,我们是要在运行此文件后,在运行输入图片路径。我们需要在此时将这张图片进行去雾处理,再输出来再往下运行。目前我无法想出将输入图片作为输入变量导入ACE.py运行的方法,所以也以失败告终。
将所有def打包成class一起import
想到这步已经是用了一天半了,因为也不知道可不可行,一直想先用第一种思路做一个solution出来,所以耽误了很多时间。但事实证明这种想法可行且很对。
问题总结
关于python中类的理解
- 类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 方法:类中定义的函数。
- 类的构造方法__init__():类有一个名为 init() 的特殊方法(构造方法),该方法在类实例化时会自动调用。
- 实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
- 实例化:创建一个类的实例,类的具体对象。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
话不多说,直接上代码!!!
1 | class HazeRemoval1: #我自己定义的类名 |
重点在于对self的理解,我一开始认为是具体变量,误认为是每个def中输入的变量,把方法中的I之类的替换为self,那就大错特错了。它会直接给你报大大的错(由于是嵌套方法,上一个方法返回的变量个数与下一个方法输入变量不匹配)。因为self不是实际意义上的变量,是你的实参,后面的所有方法都和它有关,但它不占用方法中的变量坑位。self可以理解为一个字典变量,内部存的就是对象的数据属性。
图片PIL与cv类型的转换
但是新的问题又出现了,predict中输入是用PIL中的open,得到的是图片的PIL的类型。而我们的各种opencv的形态学操作都是用图片的cv类型。因此我们在传入class后先要把图片从PIL类型转变为cv类型。
1 | def PIL2cv(self): |
同样的,进行去雾操作后的输出图片也是cv类型,而最后也要转变为PIL类型。
又一个大大大坑,float,double等类型的图片不能直接用fromarray转换为PIL类型。
不然会报以下cv2.error错误。
所以中间要加一步astype把浮点变为整型。
1 | try: |
同一张图片imshow和imwrite却不同
还有一个意外发现,就是imshow显示出的图片和imwrite保存的图片不一样。
- (1)当输入矩阵是uint8类型的时候,此时imshow显示图像的时候,会认为输入矩阵的范围在0-255之间。
- (2)如果imshow的参数是double类型的时候,那么imshow会认为输入矩阵的范围在0-1。
1 | image_uint8 = image_double.astype(np.uint8) |
再进行imshow。