如何理解这段python程序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何理解这段python程序相关的知识,希望对你有一定的参考价值。

import numpy as np
import os
from PIL import Image

def convolve(image, weight):
height, width = image.shape
h, w = weight.shape
height_new = height - h + 1
width_new = width - w + 1
image_new = np.zeros((height_new, width_new), dtype=np.float)
for i in range(height_new):
for j in range(width_new):
image_new[i,j] = np.sum(image[i:i+h, j:j+w] * weight)
image_new = image_new.clip(0, 255)
image_new = np.rint(image_new).astype('uint8')
return image_new

# image_new = 255 * (image_new - image_new.min()) / (image_new.max() - image_new.min())

if __name__ == "__main__":
A = Image.open("lena.png", 'r')
output_path = '.\\ImageConvolve\\'
if not os.path.exists(output_path):
os.mkdir(output_path)
a = np.array(A)
avg3 = np.ones((3, 3))
avg3 /= avg3.sum()
avg5 = np.ones((50, 50))
avg5 /= avg5.sum()
gauss = np.array(([0.003, 0.013, 0.022, 0.013, 0.003],
[0.013, 0.059, 0.097, 0.059, 0.013],
[0.022, 0.097, 0.159, 0.097, 0.022],
[0.013, 0.059, 0.097, 0.059, 0.013],
[0.003, 0.013, 0.022, 0.013, 0.003]))
soble_x = np.array(([-1, 0, 1], [-2, 0, 2], [-1, 0, 1]))
soble_y = np.array(([-1, -2, -1], [0, 0, 0], [1, 2, 1]))
soble = np.array(([-1, -1, 0], [-1, 0, 1], [0, 1, 1]))
prewitt_x = np.array(([-1, 0, 1], [-1, 0, 1], [-1, 0, 1]))
prewitt_y = np.array(([-1, -1,-1], [0, 0, 0], [1, 1, 1]))
prewitt = np.array(([-2, -1, 0], [-1, 0, 1], [0, 1, 2]))
laplacian4 = np.array(([0, -1, 0], [-1, 4, -1], [0, -1, 0]))
laplacian8 = np.array(([-1, -1, -1], [-1, 8, -1], [-1, -1, -1]))
weight_list = ('avg3', 'avg5', 'gauss', 'soble_x', 'soble_y', 'soble', 'prewitt_x', 'prewitt_y', 'prewitt', 'laplacian4', 'laplacian8')
print ('梯度检测:')
for weight in weight_list:
print (weight, 'R',)
R = convolve(a[:, :, 0], eval(weight))
print ('G',)
G = convolve(a[:, :, 1], eval(weight))
print ('B')
B = convolve(a[:, :, 2], eval(weight))
I = np.stack((R, G, B), 2)
if weight not in ('avg3', 'avg5', 'gauss'):
I = 255 - I
Image.fromarray(I).save(output_path + weight + '.png')

convolve 这个函数应该是 输入的numpy.array,按照权值weight,
以(i,j)点的邻域 行列式(i:i+w,j+j+h)和行列式wight进行 行列式相乘 得到的结果为新的(i,j)

说白了就是权值的相加减的问题,梯度不剃度我就不知了额
参考技术A 第一看起来很长,第二排版不行,你能用代码编辑器给发出来么。。。看得累。追问

追答

这是一个图像边缘检测的代码。代码好懂,但是具体的像sobel、prewitt、laplacian
算子还有高斯,这些为什么要这么写,我就不大知道了,不好意思。这块我没怎么接触,帮不了你。按照你的代码,我敲完了一遍,实现了11张分别被这些算法处理过的图片。个中原理还需要专门了解,抱歉。

参考技术B 边缘检测的代码,包括了sobel算子,prewitt算子和拉普拉斯算子,都是用于边缘检测 参考技术C 哪里抄来的

这么长,多看看

python-聊聊反射

反射

对于初学python可能较难理解,但反射是非常有用。

试想一下,当别的程序传入给你写的这段代码一个变量(var=“math”),这个变量是一个字符串,这个字符串是一个模块或者一个模块下的某个方法,你需要通过变量来导入此模块或者方法,如何导入此模块或方法呢,如果直接执行 import var是会出错的,因为var在你的这段代码中是一个变量, 这时就需要反射, 如何使用反射呢。

1.聊聊自省

 在计算机编程中,自省是指这种能力:检查某些事物以确定它是什么、它知道什么以及他能做什么。自省向程序员提供了极大的灵活性和控制力。

几个重要的函数:

dir函数,传入的参数是对象,返回该对象的所有属性和函数列表:

>>> dir(str)
[\'__add__\', \'__class__\', \'__contains__\', \'__delattr__\', \'__doc__\', \'__eq__\', \'__format__\', \'__ge__\', \'__getattribute__\', \'__getitem__\', \'__getnewargs__\', \'__getslice__\', \'__gt__\', \'__hash__\', \'__init__\', \'__le__\', \'__len__\', \'__lt__\', \'__mod__\', \'__mul__\', \'__ne__\', \'__new__\', \'__reduce__\', \'__reduce_ex__\', \'__repr__\', \'__rmod__\', \'__rmul__\', \'__setattr__\', \'__sizeof__\', \'__str__\', \'__subclasshook__\', \'_formatter_field_name_split\', \'_formatter_parser\', \'capitalize\', \'center\', \'count\', \'decode\', \'encode\', \'endswith\', \'expandtabs\', \'find\', \'format\', \'index\', \'isalnum\', \'isalpha\', \'isdigit\', \'islower\', \'isspace\', \'istitle\', \'isupper\', \'join\', \'ljust\', \'lower\', \'lstrip\', \'partition\', \'replace\', \'rfind\', \'rindex\', \'rjust\', \'rpartition\', \'rsplit\', \'rstrip\', \'split\', \'splitlines\', \'startswith\', \'strip\', \'swapcase\', \'title\', \'translate\', \'upper\', \'zfill\']

可以看出,string对象的所有函数,属性都列举出来了。

getatter方法,传入参数是对象和该对象的函数或者属性的名字,返回对象的函数或者属性实例,如下:

 

>>> getattr(\'str\',\'rfind\')
<built-in method rfind of str object at 0x7fc2e04c5b10>

 

callable方法,如果传入的参数是可以调用的函数,则返回true,否则返回false。

>>> callable(getattr(\'str\',\'rfind\'))
True
>>> callable(getattr(\'str\',\'__doc__\'))
False
>>> 

列出对象的所有可以执行的函数:这个地方用到了列表推导式:

>>> methodLIst = [method for method in dir(str) if callable(getattr(str,method))]
>>> print methodLIst
[\'__add__\', \'__class__\', \'__contains__\', \'__delattr__\', \'__eq__\', \'__format__\', \'__ge__\', \'__getattribute__\', \'__getitem__\', \'__getnewargs__\', \'__getslice__\', \'__gt__\', \'__hash__\', \'__init__\', \'__le__\', \'__len__\', \'__lt__\', \'__mod__\', \'__mul__\', \'__ne__\', \'__new__\', \'__reduce__\', \'__reduce_ex__\', \'__repr__\', \'__rmod__\', \'__rmul__\', \'__setattr__\', \'__sizeof__\', \'__str__\', \'__subclasshook__\', \'_formatter_field_name_split\', \'_formatter_parser\', \'capitalize\', \'center\', \'count\', \'decode\', \'encode\', \'endswith\', \'expandtabs\', \'find\', \'format\', \'index\', \'isalnum\', \'isalpha\', \'isdigit\', \'islower\', \'isspace\', \'istitle\', \'isupper\', \'join\', \'ljust\', \'lower\', \'lstrip\', \'partition\', \'replace\', \'rfind\', \'rindex\', \'rjust\', \'rpartition\', \'rsplit\', \'rstrip\', \'split\', \'splitlines\', \'startswith\', \'strip\', \'swapcase\', \'title\', \'translate\', \'upper\', \'zfill\']

2.python是如何体现反射的

globals()

这个函数返回一个map,这个map的key是全局范围内对象的名字,value是该对象的实例,在不导入任何module下,执行globals()的结果如下:

>>> globals()
{\'__builtins__\': <module \'__builtin__\' (built-in)>, \'__name__\': \'__main__\', \'__doc__\': None, \'__package__\': None}
>>> 

在导入sys后,可以发现,globals()返回的map中,多了sys module:

>>> globals()
{\'__builtins__\': <module \'__builtin__\' (built-in)>, \'__name__\': \'__main__\', \'sys\': <module \'sys\' (built-in)>, \'__doc__\': None, \'__package__\': None}

在导入sgmlib如下:

>>> import sgmllib
>>> globals()
{\'sgmllib\': <module \'sgmllib\' from \'/usr/lib64/python2.6/sgmllib.pyc\'>, \'__builtins__\': <module \'__builtin__\' (built-in)>, \'__package__\': None, \'sys\': <module \'sys\' (built-in)>, \'__name__\': \'__main__\', \'__doc__\': None}

如果导入类后,在map中,可以找到类SGMLParser

>>> from sgmllib import SGMLParser
>>> globals()
{\'sgmllib\': <module \'sgmllib\' from \'/usr/lib64/python2.6/sgmllib.pyc\'>, \'SGMLParser\': <class sgmllib.SGMLParser at 0x7fbd2754c530>, \'__builtins__\': <module \'__builtin__\' (built-in)>, \'__package__\': None, \'sys\': <module \'sys\' (built-in)>, \'__name__\': \'__main__\', \'__doc__\': None}

所以,只要将class的名字作为key,即可得到class。如下:

>>> globals()[\'SGMLParser\']
<class sgmllib.SGMLParser at 0x7fbd2754c530>
>>> parser = globals()[\'SGMLParser\']()
>>> parser
<sgmllib.SGMLParser instance at 0x7fbd2d64f1b8>

将模块引入,之后确定模块的相应类的名字,就可以得到了一个类对象,之后就可以实例化了。

3.反射详解

python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。

#!/usr/bin/env python
#-*- coding:utf-8 -*-
__author__ = \'wyf\'

class Foo(object):
    def __init__(self):
        self.name = \'chushiyaoyue\'

    def func(self):
        return \'func\'

obj = Foo()#实例化一个对象

# #### 检查是否含有成员 ####
hasattr(obj, \'name\') #True
hasattr(obj, \'func\') #True

# #### 获取成员 ####
getattr(obj, \'name\')
getattr(obj, \'func\')
#chushiyaoyue
#<bound method Foo.func of <__main__.Foo object at 0x0000000002C5F4A8>>
# #### 设置成员 ####
setattr(obj, \'age\', 18)#添加属性
setattr(obj, \'show\', lambda num: num + 1)#添加方法
# print vars(obj)
#{\'age\': 18, \'name\': \'chushiyaoyue\', \'show\': <function <lambda> at 0x0000000002A46128>}#已经添加了一个属性和一个方法
# # #### 删除成员 ####
delattr(obj, \'name\')
delattr(obj, \'func\')

__import__(\'模块名字\')

from 包 import 模块名 as 别名 ====等于=== 别名 = __import__("模块名的字符串")

针对该模块同一级下另外一个目录,也就是包,而这个包下有另一个包,而我们需要导入的模块还在其下面,这时候,不能应用包.包.模块作为字符串传入__import__来导入了,因为其只会导入第一层包,需要加入一个参数fromlist = True

a = __import__\'\'#基础的导入
__import__("a.b.c.file.login",fromlist=True)#多层级的导入
__import__("a.b.c.file.login")  #是不对的 只导入了a目录 包

python中一切实物都是对象,类,模块也是对象!反射是通过字符串的形式操作对象相关的成员!

类是对象:

 1 #!/usr/bin/env python
 2 #-*- coding:utf-8 -*-
 3 __author__ = \'wyf\'
 4 
 5 class Foo(object):
 6 
 7     staticField = "test123"
 8 
 9     def __init__(self):
10         self.name = \'chushiyaoyue\'
11 
12     def func(self):
13         return \'func\'
14 
15     @staticmethod
16     def bar():
17         return \'bar\'
18 
19 print getattr(Foo, \'staticField\')
20 print getattr(Foo, \'func\')
21 print getattr(Foo, \'bar\')

模块是对象:

1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3  
4 def dev():
5     return \'dev\'
home.py
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3   
 4 """
 5 程序目录:
 6     home.py
 7     index.py
 8   
 9 当前文件:
10     index.py
11 """
12   
13   
14 import home as obj
15   
16 #obj.dev()
17   
18 func = getattr(obj, \'dev\')
19 func() 

实例小练习:根据用户输入的url执行相关的功能

 1 #!/usr/bin/env python
 2 #-*- coding:utf-8 -*-
 3 __author__ = \'wyf\'
 4 
 5 def login():
 6     return \'login\'
 7 
 8 def logout():
 9     return \'logout\'
10 
11 def nb():
12     return \'特别牛逼的页面\'
account.py

最简单粗暴的方法,简单很容易想到,但是如果方法一多,你要写很多代码

 1 #!/usr/bin/env python
 2 #-*- coding:utf-8 -*-
 3 __author__ = \'wyf\'
 4 
 5 from lib import account
 6 
 7 url = raw_input(\'请输入url:\')
 8 
 9 if url.endswith(\'login\'):
10     r = account.login()
11     print r
12 
13 elif url.endswith(\'logout\'):
14     r = account.logout()
15     print r
16 
17 elif url.endswith(\'nb\'):
18     r = account.nb()
19     print r
20 
21 else:
22     print \'404\'
简单的方式

使用反射的方式,一步到位不管你有多少个方法调用,我都支持

 1 #!/usr/bin/env python
 2 #-*- coding:utf-8 -*-
 3 __author__ = \'wyf\'
 4 
 5 from lib import account
 6 url = raw_input(\'请输入url:\')
 7 target_module,target_func = url.split(\'/\')
 8 
 9 m = __import__(\'lib.\',target_module,fromlist=True)
10 if hasattr(m,target_func):#判断这个函数里面是否存在这个方法
11     target_func = getattr(account,inp)#获取这个方法
12     r = target_func()#执行这个方法
13     print r
14 else:
15     print \'404\'

 

以上是关于如何理解这段python程序的主要内容,如果未能解决你的问题,请参考以下文章

理解Python命名机制

理解Python的双下划线命名

Python 中的 if __name__ == '__main__' 该如何理解

简介

装饰器的理解

大话 Python:python 进阶提升 -- 如何理解垃圾回收机制及应用