Python PIL简单的图片处理

/ 0评 / 1

为了解决全景图片拼缝的问题,要去处理一张黑白相间的格子图片,觉得别的方法太麻烦了,直接上python吧。
python读取图片信息的方法还是很简单的,因为有库,我这里使用的是PIL这个库,直接使用pip安装就好了,

pip install Pillow

然后引入就可以使用了

from PIL import Image
im = Image.open('res5.png')
width = im.size[0]
height = im.size[1]
print "/* width:%d */" % (width)
print "/* height:%d */" % (height)

pil处理图片,验证,处理
大小,格式 过滤
压缩,截图,转换

#图片的基本参数获取  
try:  
    from PIL import Image, ImageDraw, ImageFont, ImageEnhance  
except ImportError:  
    import Image, ImageDraw, ImageFont, ImageEnhance  
  
def compress_image(img, w=128, h=128):  
    ''''' 
    缩略图 
    '''  
    img.thumbnail((w,h))  
    im.save('test1.png', 'PNG')  
    print u'成功保存为png格式, 压缩为128*128格式图片'  
  
def cut_image(img):  
    ''''' 
    截图, 旋转,再粘贴 
    '''  
    #eft, upper, right, lower  
    #x y z w  x,y 是起点, z,w是偏移值  
    width, height = img.size  
    box = (width-200, height-100, width, height)  
    region = img.crop(box)  
    #旋转角度  
    region = region.transpose(Image.ROTATE_180)  
    img.paste(region, box)  
    img.save('test2.jpg', 'JPEG')  
    print u'重新拼图成功'  
  
def logo_watermark(img, logo_path):  
    ''''' 
    添加一个图片水印,原理就是合并图层,用png比较好 
    '''  
    baseim = img  
    logoim = Image.open(logo_path)  
    bw, bh = baseim.size  
    lw, lh = logoim.size  
    baseim.paste(logoim, (bw-lw, bh-lh))  
    baseim.save('test3.jpg', 'JPEG')  
    print u'logo水印组合成功'  
  
def text_watermark(img, text, out_file="test4.jpg", angle=23, opacity=0.50):  
    ''''' 
    添加一个文字水印,做成透明水印的模样,应该是png图层合并 
    http://www.pythoncentral.io/watermark-images-python-2x/ 
    这里会产生著名的 ImportError("The _imagingft C module is not installed") 错误 
    Pillow通过安装来解决 pip install Pillow 
    '''  
    watermark = Image.new('RGBA', img.size, (255,255,255)) #我这里有一层白色的膜,去掉(255,255,255) 这个参数就好了  
  
    FONT = "msyh.ttf"  
    size = 2  
  
    n_font = ImageFont.truetype(FONT, size)                                       #得到字体  
    n_width, n_height = n_font.getsize(text)  
    text_box = min(watermark.size[0], watermark.size[1])  
    while (n_width+n_height <  text_box):  
        size += 2  
        n_font = ImageFont.truetype(FONT, size=size)  
        n_width, n_height = n_font.getsize(text)                                   #文字逐渐放大,但是要小于图片的宽高最小值  
  
    text_width = (watermark.size[0] - n_width) / 2  
    text_height = (watermark.size[1] - n_height) / 2  
    #watermark = watermark.resize((text_width,text_height), Image.ANTIALIAS)  
    draw = ImageDraw.Draw(watermark, 'RGBA')                                       #在水印层加画笔  
    draw.text((text_width,text_height),  
              text, font=n_font, fill="#21ACDA")  
    watermark = watermark.rotate(angle, Image.BICUBIC)  
    alpha = watermark.split()[3]  
    alpha = ImageEnhance.Brightness(alpha).enhance(opacity)  
    watermark.putalpha(alpha)  
    Image.composite(watermark, img, watermark).save(out_file, 'JPEG')  
    print u"文字水印成功"  
  
#等比例压缩图片  
def resizeImg(img, dst_w=0, dst_h=0, qua=85):  
    ''''' 
    只给了宽或者高,或者两个都给了,然后取比例合适的 
    如果图片比给要压缩的尺寸都要小,就不压缩了 
    '''  
    ori_w, ori_h = im.size  
    widthRatio = heightRatio = None  
    ratio = 1  
  
    if (ori_w and ori_w > dst_w) or (ori_h and ori_h  > dst_h):  
        if dst_w and ori_w > dst_w:  
            widthRatio = float(dst_w) / ori_w                                      #正确获取小数的方式  
        if dst_h and ori_h > dst_h:  
            heightRatio = float(dst_h) / ori_h  
  
        if widthRatio and heightRatio:  
            if widthRatio < heightRatio:  
                ratio = widthRatio  
            else:  
                ratio = heightRatio  
  
        if widthRatio and not heightRatio:  
            ratio = widthRatio  
  
        if heightRatio and not widthRatio:  
            ratio = heightRatio  
  
        newWidth = int(ori_w * ratio)  
        newHeight = int(ori_h * ratio)  
    else:  
        newWidth = ori_w  
        newHeight = ori_h  
  
    im.resize((newWidth,newHeight),Image.ANTIALIAS).save("test5.jpg", "JPEG", quality=qua)  
    print u'等比压缩完成'  
  
    ''''' 
    Image.ANTIALIAS还有如下值: 
    NEAREST: use nearest neighbour 
    BILINEAR: linear interpolation in a 2x2 environment 
    BICUBIC:cubic spline interpolation in a 4x4 environment 
    ANTIALIAS:best down-sizing filter 
    '''  
  
#裁剪压缩图片  
def clipResizeImg(im, dst_w, dst_h, qua=95):  
    ''''' 
        先按照一个比例对图片剪裁,然后在压缩到指定尺寸 
        一个图片 16:5 ,压缩为 2:1 并且宽为200,就要先把图片裁剪成 10:5,然后在等比压缩 
    '''  
    ori_w,ori_h = im.size  
  
    dst_scale = float(dst_w) / dst_h  #目标高宽比  
    ori_scale = float(ori_w) / ori_h #原高宽比  
  
    if ori_scale <= dst_scale:  
        #过高  
        width = ori_w  
        height = int(width/dst_scale)  
  
        x = 0  
        y = (ori_h - height) / 2  
  
    else:  
        #过宽  
        height = ori_h  
        width = int(height*dst_scale)  
  
        x = (ori_w - width) / 2  
        y = 0  
  
    #裁剪  
    box = (x,y,width+x,height+y)  
    #这里的参数可以这么认为:从某图的(x,y)坐标开始截,截到(width+x,height+y)坐标  
    #所包围的图像,crop方法与php中的imagecopy方法大为不一样  
    newIm = im.crop(box)  
    im = None  
  
    #压缩  
    ratio = float(dst_w) / width  
    newWidth = int(width * ratio)  
    newHeight = int(height * ratio)  
    newIm.resize((newWidth,newHeight),Image.ANTIALIAS).save("test6.jpg", "JPEG",quality=95)  
    print  "old size  %s  %s"%(ori_w, ori_h)  
    print  "new size %s %s"%(newWidth, newHeight)  
    print u"剪裁后等比压缩完成"  
  
if __name__ == "__main__":  
    im = Image.open('test.jpg')  #image 对象  
    compress_image(im)  
  
    im = Image.open('test.jpg')  #image 对象  
    cut_image(im)  
  
    im = Image.open('test.jpg')  #image 对象  
    logo_watermark(im, 'logo.png')  
  
    im = Image.open('test.jpg')  #image 对象  
    text_watermark(im, 'Orangleliu')  
  
    im = Image.open('test.jpg')  #image 对象  
    resizeImg(im, dst_w=100, qua=85)  
  
    im = Image.open('test.jpg')  #image 对象  
    clipResizeImg(im, 100, 200) 

访问图片中的像素,我这里是将图片转换成矩阵来操作的,首先来安装两个科学计算库

pip install numpy
pip install scipy

引入库进行图片操作

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
img=np.array(Image.open('res.png'))  #打开图像并转化为数字矩阵
plt.figure("dog")
plt.imshow(img)
plt.axis('off')
plt.show()

#这些方法来读取图片信息
print img.shape  
print img.dtype 
print img.size 
print type(img)

img=np.array(Image.open('res.png').convert('L'))
rows,cols=img.shape
for i in range(rows):
    for j in range(cols):
        if (img[i,j]<=128):
            img[i,j]=0
        else:
            img[i,j]=1

如果要对多个像素点进行操作,可以使用数组切片方式访问。切片方式返回的是以指定间隔下标访问 该数组的像素值。下面是有关灰度图像的一些例子

img[i,:] = im[j,:] # 将第 j 行的数值赋值给第 i 行
img[:,i] = 100 # 将第 i 列的所有数值设为 100
img[:100,:50].sum() # 计算前 100 行、前 50 列所有数值的和
img[50:100,50:100] # 50~100 行,50~100 列(不包括第 100 行和第 100 列)
img[i].mean() # 第 i 行所有数值的平均值
img[:,-1] # 最后一列
img[-2,:] (or im[-2]) # 倒数第二行

评论已关闭。