Python论坛  - 讨论区

标题:[python-chinese] Python and Image processing

2005年10月16日 星期日 20:05

makeyunbad makeyunbad at gmail.com
Sun Oct 16 20:05:54 HKT 2005

在 05-10-16,suya<su1981ya at 163.com> 写道:
> Hello Everyone,
>
>     请问各位有没有用python做图象处理的?我希望使用PIL做图象处理,但是苦于没有这方面的例子代码。
>     有没有人对这方面比较熟悉的?给介绍一下! 先谢过了
>

这是篇中文的介绍:
http://66.102.7.104/search?q=cache:zmdU0dsVP2oJ:www.dormforce.net/Blog/Attachment/159+pil+python&hl;=zh-CN&lr;=lang_zh-CN

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2005年10月16日 星期日 20:55

Zoom Quiet zoom.quiet at gmail.com
Sun Oct 16 20:55:54 HKT 2005

应该说有很多介绍的哪!?!?
我收集的比较全的就直接贴这儿了:
Python中文社区

Python,PIL,ImageMagick,PythonCOM --我们能实现什么
作者:lihuaxia from 简单生活

前阵子,我的一个朋友想要一个web图库(gallery),我本着方便别人也方便自己的原则,给他在众多的opensource方案中选择了php+mysql中gallery的佼佼者:4images。这是个德国软件,php的,图片用文件系统保存,数据关系放在mysql中,程序写得挺好,里面还有自动缩略图片的接口,用的是gd或者imagemagick。本来以为能够满足他所有的需要,后来他告诉我,"急需"一个自动往图片上印上网站的log或者文字的功能。
熟悉php的哥们都知道,gd已经不支持gif了,我的朋友是个美工,很多gif图片,于是我翻看imagemagick的文档,可以办到,嵌了几行代码,实现了。于是他就觉得不满足了,想要个在线剪切、往图片上写字、旋转图片....
等他说出滤镜的时候,我已经人间蒸发了。
其实,我觉得要实现那些功能并不是不可能。如果给我时间、充分的考虑,是可以做出来的。由网页客户端发送给服务器,需要进行的操作(copy,
parse,cut,replace...),具体参数(比如坐标、颜色值、字体、文字....)。由服务端程序执行需要进行的imagemagick命令,比如在php下用system(convert
.....)这样,也可以通过php的imagick来实现。
但是,这并不是我最想要的,我觉得要想做出我真正想要的东西,得用python--这个我最喜欢的语言来实现。为什么呢?请听我的理由。

1,python有非常好的图形接口,对于图形的显示、x界面、win界面、客户端应用控件,构造起来非常的容易。
2,真正的"完全面向对象",对于这种复杂程度的应用,很容易描述。比目前的php4x的非常牵强的面向对象机制,要好得多。
3,数据存储的特点,python的对象存储,可以直接将图像处理过程进行非常直接的描述,我的意思是说,用类描述图片的各种属性,构造各种方法、过程来描述图片处理的操作和过程,用真正完全面向对象的python对象来进行描述。
另外,大家应该都用过photoshop吧,它可以undo,用b/s或者c/s的方式,如何实现undo的功能呢?我觉得对对象的直接存储,是个非常简单的办法。
4,python的执行效率不高,但是在python层面仅仅执行操作命令的生成->解析->解释->发送给图片处理引擎,这些计算,并不是python执行效率的瓶颈。换句话说,python执行中间操作,把繁重的操作留给系统。况且,这些对字符串的操作、对象属性的存取,恰恰是python擅长的。
1.客户端的实现
1.1 b/s 是个不错的主意,有个好处就是,可以跟Python的另外一大工具--zope相结合,似乎zope的产品中已经有了PIL这样的应用,有了不错的图形接口。此外,用户系统,权限管理、操作纪录、workflow等很多东西,都能省却很多工作。zope对象的存储的容量以前是个问题,现在已经不是问题了。
当然,b/s方式也有不足,主要在于对鼠标行为的响应支持,很欠缺。对于那些复杂的消息响应,显得无能为力。(如:拖放、 调整角度、调整大小)

1.2 c/s 在鼠标消息方面,就显得游刃有余了。"可变化的布景"就能解决很多问题,那些复杂的鼠标消息,已经有了相应的非常标准的接口。但是,客户端的更新就有些麻烦了,需要重新下载软件。

2.服务端的实现
2.1 图片计算、处理接口
2.1.1 PIL(Python Imaging Library)
作者自己的介绍:Python图形库,提供给python图形处理能力,它支持很多种格式的图片,具有强有力的图形图片的处理能力当前版本是PIL1.1.4。从python1.5.2测试到python2.3。

它好得没法说,python爱好者们肯定都是耳熟能详,尤其是那些在zope上面安装过PIL产品的朋友们,对它的图形处理能力肯定是非常的有信心。对于我们这个话题来说,PIL的好处还在于,它也是python的,在于客户端进行交互的时候,会有很多便利。是否能够像zope那样使用xmlrpc传送
python对象或者python函数?

2.1.2 ImageMagick
作者自己的介绍:ImageMagickTM
6.0.1是一个强大的工具包和类库,可以读写处理很多格式的图片,包括常见的tiff,jpeg,png,pdf,photocd,gif.使用她,你可以动态的创建web图片。
也可以修改图片尺寸、旋转、锐化、淡化颜色、增加特殊效果等等,然后把结果存储为各种各样的图片格式。使用ImageMagick可以通过命令行脚本直接调用,也可以通过编程接口,比如:c,c++,perl,java,php,python,ruby等编程语言。已经提供了的Svg性能的高质量2D表达。ImageMagick关注于效果,最小化错误,并且提供了稳定的APIs和ABIs。

它是一套应用程序,文章结尾将介绍convert这个非常有用的命令,通过这个程序,我们可以调用Imagemagick的核心API,来处理图片,这里的处理,是各种图片的操作,包括新图片、拷贝、剪切、合并、生成动画、解析psd图片的图层等等,可以说,所有的我可以做的图片操作,都可以使用
convert这个命令来实现。这里必须告诉大家,我基本上是个图片白痴,对图片的处理仅仅停留在缩略图,给图片文字加logo这些基本的操作上面,希望大家能把自己做的图片处理的convert脚本提供出来,供我这样的人使用。

2.2 服务程序 Python&文件储存
我对python的对象机制数据库的印象还停留在zodb上,单独的使用zodb是一个保存python对象的最简单的方法吧?使用关系数据库来进行对
python对象的保存,我还没有进行过这样的应用开发,希望大家能够补充这方面的资料。Z对象数据库现在已经可以单独于zope来使用了吧?另外,我的印象中,还有它的缓慢、recatalog的资源占用的问题。很久不用了,不知道现在的样子。

3.其他问题

3.1 web界面的问题
这里我只想说,如果采用b/s的架构来实现这个想法,在客户端界面的问题上是很不好解决的。
想想用javascript实现那些复杂的界面消息响应,是啊,肯定可以实现,但是也许在实现以后,一个用netscape的哥们会告诉你,在他的浏览器里头,什么也实现不了。
忘了netscape4和ie4吧,要兼顾它们,可能需要翻看那些已经发黄了的css的知识的书籍,还有厚厚的javascript的早期的浏览器类型对比资料,然后在服务器端判断user-agent,提供给用户不同的javascript+css的实现。当然,还有那些更加难对付的浏览器。即便是ie
的5x,都有问题的,从5->5.5的改变中,都有不少的难对付的更改。这不是我们的错,可能也不是任何人的错,谁让着世界上不是只存在一个浏览器呢,想让他们统一html对象机制和接口,是不可能的。我甚至怀疑他们是故意造成现在的状况。除非你不想管其他浏览器或者其他版本的浏览器的用户。
那个bindows不知道能不能提供帮助,我见过有的朋友用它实现了非常了不起的ie浏览器的应用
Kaneboy: 我个人认为这是一对非常好的伙伴,结合起来,可以完成我们想象不到的非常Cool的应用,JavaScript用于客户端界面的显示和处理,
XMLHTTP用于客户端与服务器的信息传输。
JavaScript在客户端的表现力不容置疑,看看www.bindows.net所表示出来的能力,利用JavaScript几乎可以实现
Windows应用程序所能干的大部分事情,而且Bindows提供了一个封装好的可以直接利用的JS类库,省了我们大把的力气。
XMLHTTP一直以来常被用于实现"无刷新"的Web页面,它和JavaScript配合,可以完成数据从服务器和客户端的传输。Janc是
Lostinet实现的一套.NET类库,完整的封装了服务器端XMLHTTP接口,程序员不需要了解XMLHTTP的细节,就可以编写自己的
XMLHTTP应用系统。(Lostinet好像在做Janc的下一个版本,叫做Rane)想想,用Bindows构建客户端的显示界面,而与服务器的传输用Janc来实现,岂不是天作之合?Web系统原有的界面交互性差、页面刷新等问题都可以很好的解决。

3.2 在windows下

3.2.1 PIL在windows下的使用
安装python以后在这个页面http://www.pythonware.com/products/pil/index.htm跟据版本选择相应的安装文件python会自动地找到你的python安装,在里面命令行测试一下,就能知道是否安装成功。对图片的路径的引用,需要使用windows路径。

3.2.2 Imagemagick在windows下的使用
ImageMagick在windows下面安装很容易,直接在这里ftp://ftp.imagemagick.org/pub/ImageMagick/beta/ImageMagick-6.0.2-Q16-windows-dll.exe找到windows的安装文件就可以。但是在windows下运行命令行的时候,就需要指定windows下imagemagick的命令来执行了,比如:

c:\im\bin\convert.exe -geometry 120x120 c:\big.jpg c:\small.jpg


3.2.3 在windows下,使用pil或者imagemagick还能做的
我曾经尝试使用pythoncom+pil制作了被python.dll执行的com组件,由asp调用,用来完成在asp下很麻烦的图片处理,缩略等小应用,觉得挺方便的。大概就是按照pythoncom的接口要求,封装几个pil的小方法,注册以后在asp网页里头调用,完成那些以前必须用
delphi或者vcvb作的工作。
asp代码:

  set o = createObject('imageServer')
  o.resizeTo(...)


python代码:

#下面代码中用到的_reg_clsid_是这么来的,在python命令行下:
#>>> import pythoncom
#>>> print pythoncom.CreateGuid()
#{77F5219D-8351-4489-96E6-EBE2915E6DEF}

#这里是命令行取得guid


#需要用一个命令取得classID,然后用命令行注册/注销com
import Image
class ImageServer:
	_public_methods_ = ['resizeTo']
	_public_attrs_   = ['img']
	_reg_progid_ = "ImageServer.Application"
	_reg_clsid_ = "{77F5219D-8351-4489-96E6-EBE2915E6DEF}"

	def __init__(self):
		self.img = None          #图片2进制数据或者文件句柄
		self.nSize = [None,None] #图片size
		self.Type = ""           #这里是图片的格式如gif,jpg,psd之类
	
	def resizeTo(self,sp,dp,mx):
		self.img  = Image.open(sp)
		self.Type = self.img.tile[0][0] # 应改成 img.format
		self.resize(self.img.size,mx)
		self.img.resize(self.nSize).save(dp, self.Type) #这里的调用不好
		return self.img


                            #里面的计算本来是应付图片缩略后大小不一,
	def resize(self,size,mx):#排列不好看写得。可能有问题。
		if size[0]>=size[1]:
			self.nSize[0] = mx
			self.nSize[1] = mx*size[1]/size[0]
		else:
			self.nSize[0] = mx*size[0]/size[1]
			self.nSize[1] = mx

if __name__ == '__main__':
	import win32com.server.register,sys
	if "-unregister" in sys.argv: #这里是注销pythoncom的接口
		print "UNRegistering COM Server"
		win32com.server.register.UnregisterClasses(ImageServer)
	else:    #这里是注册pythoncom的接口
		print "Registering COM Server"
		win32com.server.register.UseCommandLine(ImageServer)
	#上面的代码是个半截版本,属性的存取有点问题,运行可能有错误
	#原来的代码找不到了

pythoncom是个很好的东西,在windows系统中预先载入python解析器,用com的原理,提供一些服务。由于
python的类库非常广大,几乎涵盖了所有的中小型应用,所以,对于有些地方,用起来很方便。需要注意的就是,还没有负载量高的网站用
pythoncom的先例,python.dll到底会给机器带来多大的压力,不太清楚。
csdn上有个叫socketref(代码注释作者runonce)的哥们用pythoncom简单包装了一下ado,代码挺有意思,大家可以来看看。网页地址和他的联系方式都已经找不到了,只有代码:

  ############################################
# 功能: ado数据访问包装
# 日期:2003-01-10
# 创建:runonce
# 历史:	
#	2003-01-10  创建
##############################################

from win32com.client import *
import pythoncom
import string
from adoconst import *

#定义参数类型
STRING = adVarChar
INT = adInteger
DOUBLE = adDouble


	
class PAdo:
	""" Ado数据访问包装类
	"""
	def __init__(self,cnnstr='',bOpen=1):
		"cnnstr--ado 数据连接字符串,bopen--是否自动打开"
		self.cnnstr =cnnstr
		self.adoConn=None
		self.rs=None
		self.adoConn = Dispatch('ADODB.Connection')
		self.rs=Dispatch('ADODB.Recordset')
		if bOpen==1 :
			self.adoConn.Open(cnnstr)
			
	def Close(self):
		self.adoConn=None
		self.rs=None
		
	def	getTables(self):
		" 获取数据库所有表名称"
		
		adoRs = self.adoConn.OpenSchema(20)  #取数据库所有表
		adoRs.MoveFirst()
		ar=[]
		while not adoRs.EOF:
		    ar.append(str(adoRs.Fields.Item('TABLE_NAME')))
		    adoRs.MoveNext()
		return ar
		
	def getFields(self,rs): #recordset
		"取记录集字段信息"
		fds=[]
		for i in range(1,rs.Fields.Count):
			fds.append(rs.Fields.Item(i).Name)
		return fds
	
	def Select(self,sql):
		"""执行查询操作,多参引入
			不采用参数占位符方式,传入的sql直接执行	
		03.0109
		"""
		self.rs=Dispatch('ADODB.Recordset')
		self.rs.Open(sql,self.adoConn)
		#
		#ar=[]
		#while not self.rs.EOF:
		#	print self.rs.Fields.Item('NAME').Value
		#	ar.append(self.rs.Fields.Item('NAME').Value)
		#	self.rs.MoveNext()
		
		return self.rs
		
		
	def Execute(self,sql,*params):
		"""
			sql-- sql执行语句,
           如果是带参数则形式为 insert into tablename (name) values(:name),同bcb
			params --每个参数是一个4元组,代表参数的具体信息 ,
           (name,type,size,value) ,撤销size,成为3元组合
			params=None,指定sql为正常sql(不带参数占位符号)
		使用方法:
			ado.Execute(
           'insert into basicinfo (name,type,dt,v2)
values(?,?,?,?)',['name',STRING,'11'],
			['type',STRING,'类型'],
           ['dt',STRING,'2002-01-12 12:12:01'],
           ['v2',DOUBLE,111111111.231])


		--未进行错误保护
		
		"""
		sql = string.upper(sql)
		print sql
		param = Dispatch('ADODB.Parameter')
		cmd = Dispatch('ADODB.Command')
		cmd.ActiveConnection = self.adoConn
		cmd.CommandText= sql
		if(params !=None):
			for ele in params:  #len(params) 个参数字段带入
				print ele[0],ele[1],ele[2]
				if ele[1]==STRING:
					size = len(unicode(ele[2]))
				if ele[1]==INT:
					size = 4
				if ele[1]==DOUBLE:
					size =8
				cmd.Parameters.Append(cmd.CreateParameter(ele[0],ele[1],1,size,ele[2]))
		cmd.Execute()
	
		
	def GetRecordCount(self,adors):
		"取记录集记录总数"
		adors.MoveFirst()
		cnt=0
		while not adors.EOF:
			cnt+=1
			adors.MoveNext()
		adors.MoveFirst()
		return cnt


		
########################################################
#########################################################

if __name__=="__main__":
	ado = PAdo('Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=data.mdb;Persist Security Info=False')
	rs = ado.Select('select * from basicinfo')
	print ado.getFields(rs)	
	#print ado.GetRecordCount(rs)
	#ado.doExec('insert into basicinfo (name) values (?)')
	#ado.Execute('insert into basicinfo (name,type,dt,v2)
values(?,?,?,?)',['name',STRING,'11'],
	#['type',STRING,'类型'],['dt',STRING,'2002-01-12
12:12:01'],['v2',DOUBLE,111111111.231])
	
	






4.本文涉及的一些工具
4.1.1 PIL (Python Imaging Library)
如果你是个python爱好者,别放过它。
地址:http://www.pythonware.com/products/pil/index.htm
手册:http://www.pythonware.com/library/pil/handbook/index.htm
文章:http://www.pythonware.com/products/pil/articles/index.htm
所有子类:
Image 首要类,用来描绘图片对象。

#获取图片旋转显示
import Image
im = Image.open("bride.jpg")
im.rotate(45).show()
import glob
#指定一批图片,按照指定尺寸缩略
for infile in glob.glob("*.jpg"):
    file, ext = os.path.splitext(infile)
    im = Image.open(infile)
    im.thumbnail((128, 128), Image.ANTIALIAS)
    im.save(file + ".thumbnail", "JPEG")


ImageChops 图片计算类
ImageColor 颜色类
ImageDraw 平面画图类

#画条灰线输出
import Image, ImageDraw
im = Image.open("lena.pgm")
draw = ImageDraw.Draw(im)
draw.line((0, 0) + im.size, fill=128)
draw.line((0, im.size[1], im.size[0], 0), fill=128)
del draw
im.save(sys.stdout, "PNG")


ImageEnhance 图片效果类

#锐化图片
import ImageEnhance
enhancer = ImageEnhance.Sharpness(image)
for i in range(8):
    factor = i / 4.0
    enhancer.enhance(factor).show("Sharpness %f" % factor)

ImageFile 图片文件存取类

#复制一幅图片
import ImageFile
fp = open("lena.pgm", "rb")
p = ImageFile.Parser()
while 1:
    s = fp.read(1024)
    if not s:
        break
    p.feed(s)
im = p.close()
im.save("copy.jpg")

ImageFileIO 图片流类
ImageFilter 图片过滤类

import ImageFilter
im1 = im.filter(ImageFilter.BLUR)
im2 = im.filter(ImageFilter.MinFilter(3))
im3 = im.filter(ImageFilter.MinFilter)

ImageFont 字形类,用于画图

#获取arial.pil字体,在图片上用这种字体写字
import ImageFont, ImageDraw
font = ImageFont.load("arial.pil")
draw = ImageDraw.Draw(image)
draw.text((10, 10), "hello", font=font)

ImageGrab 图片抓取类,可以抓屏,或者从剪切板里获取图片

#检查剪切板中是否有图片
im = ImageGrab.grabclipboard()
if isinstance(im, Image.Image):
    ... got an image ...
elif im:
   for filename in im:
       try:
           im = Image.open(filename)
       except IOError:
           pass # ignore this file
       else:
           ... got an image ...
else:
    ... clipboard empty ...


ImageOps 图片处理类
ImagePath 路径队列类
ImagePalette
ImageSequence 队列包装类
ImageStat 图片属性类
ImageTk Tkinter支持类
ImageWin Windows支持类
PSDraw Postscript支持类

4.1.2 ImageMagick
不管你用什么语言写代码,了解一下imagemagick真的是有好处的。
地址:http://imagemagick.org/
下载:http://imagemagick.org/www/download.html?
实例:http://imagemagick.org/images/examples.jpg
Imagemagick的python接口:http://sourceforge.net/projects/pylab
另一个Imagemagick的python接口:ftp://ftp.imagemagick.org/pub/ImageMagick/python
这里是几个小convert命令的使用:
convert命令,能够将一幅某种格式的图片进行若干种处理,然后用某种图片格式进行输出。
命令的基本格式: convert [ 选项 ... ] 原始图片 [ 选项 ... ] 输出图片
制作缩略图

convert -geometry 120x120 big.jpg small.jpg

a,需要注意的就是 -geometry 后面的参数是图像大小参数,要想让图片缩略以后显示正常,需要输入正确比例的尺寸。
b,图片的格式,如果需要转换,直接可以通过图片的扩展名的变化,就可以实现,比如,small.gif。
c,gif动画也可以通过这种方式进行直接缩略,但是,所略的效果,需要看gif动画的制作质量,色差,帧数等等因素。
d,quality参数的使用,在缩略的时候,往往会考虑到控制缩略效果,quality这个参数,正是通过给"质量"付值,来控制处理图片的质量。默认得值是75,使用的时候:
-quality 80。

制作动画

convert -delay 10 a1.gif -delay 10 a2.gif -delay 20 a3.gif a.gif

a,将a1.gif,a2.gif,a3.gif三个gif图片,按照10,10,20的延迟时间,制作成一个a.gif的动画
b,简便的写法,convert -delay 10 a*.gif a.gif。即将这些图片,按照10的delay制作成gif动画。

给图片加上有色边框

convert -bordercolor black -border 25x25 sou.jpg des.gif

a,-bordercolor参数是设定便框的颜色
b,-border设定围起来的区域大小

发现一个国人做的学习笔记,很是不错 http://hedong.3322.org/archives/000339.html,介绍的很详细。
4.1.3 ZODB(zope对象数据库)
主页:http://www.zope.org/Wikis/ZODB/FrontPage

4.1.4 bindows
一套很好的javascript开发工具,可以实现非常难得界面。做web的朋友们应该收藏。见过一个外国朋友做了个邮件客户端,挺好的,比outlook好。国人也有不少用这个开发的,似乎用web完全模仿传统界面很时髦?
主页:http://www.bindows.net

lihuaxia 贴于python.cn 简单生活


在 05-10-16,makeyunbad<makeyunbad at gmail.com> 写道:
> 在 05-10-16,suya<su1981ya at 163.com> 写道:
> > Hello Everyone,
> >
> >     请问各位有没有用python做图象处理的?我希望使用PIL做图象处理,但是苦于没有这方面的例子代码。
> >     有没有人对这方面比较熟悉的?给介绍一下! 先谢过了
> >
>
> 这是篇中文的介绍:
> http://66.102.7.104/search?q=cache:zmdU0dsVP2oJ:www.dormforce.net/Blog/Attachment/159+pil+python&hl;=zh-CN&lr;=lang_zh-CN
>
> _______________________________________________
> python-chinese list
> python-chinese at lists.python.cn
> http://python.cn/mailman/listinfo/python-chinese
>
>
>


--
[Time is unimportant, only life important!]

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2005年10月16日 星期日 21:12

suya su1981ya at 163.com
Sun Oct 16 21:12:03 HKT 2005

Hello makeyunbad,

    谢谢两位的快捷帮助。你们所说的我也都看过了,其实我真正想要的,也是初学者们想要的,是一个完整的图像处理pIL程序,就像《Visual C++数字图像处理》所带的源代码一样。这样我们不管是学习还是使用都非常容易。我没有找到这方面的例子。
    我倒有个想法,不如我们建一个开源的图像处理python解决方案,以后再有类似的问题可以直接参考。大家觉得怎么样?
    不过就像文中所说,PIL在复杂的图像处理方面还有点力所不及。大家有好的建议没?

Best regards, 
  
======= At 2005-10-16, 20:05:54 you wrote: =======

>在 05-10-16,suya<su1981ya at 163.com> 写道:
>> Hello Everyone,
>>
>>     请问各位有没有用python做图象处理的?我希望使用PIL做图象处理,但是苦于没有这方面的例子代码。
>>     有没有人对这方面比较熟悉的?给介绍一下! 先谢过了
>>
>
>这是篇中文的介绍:
>http://66.102.7.104/search?q=cache:zmdU0dsVP2oJ:www.dormforce.net/Blog/Attachment/159+pil+python&hl;=zh-CN&lr;=lang_zh-CN
>_______________________________________________
>python-chinese list
>python-chinese at lists.python.cn
>http://python.cn/mailman/listinfo/python-chinese
>

= = = = = = = = = = = = = = = = = = = =
			
suya
su1981ya at 163.com
2005-10-16


[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

如下红色区域有误,请重新填写。

    你的回复:

    请 登录 后回复。还没有在Zeuux哲思注册吗?现在 注册 !

    Zeuux © 2025

    京ICP备05028076号