设为首页 收藏本站
查看: 850|回复: 0

[经验分享] 纯Python综合图像处理小工具(4)自定义像素级处理(剪纸滤镜)

[复制链接]

尚未签到

发表于 2015-11-29 08:55:37 | 显示全部楼层 |阅读模式
  
  上一节介绍了python PIL库自带的10种滤镜处理,现成的库函数虽然用起来方便,但是对于图像处理的各种实际需求,还需要开发者开发自定义的滤镜算法。本文将给大家介绍如何使用PIL对图像进行自定义的像素级操作
  
  本文以剪纸风格图像处理作为例子:(算法借鉴了残阳似血的博客http://qinxuye.me/,特此鸣谢。)
  原图:
DSC0000.jpg
  处理后:
DSC0001.png
  
  1.首先将处理参数预先设定好。设定阈值threshold,该阈值会用来区分作为目标颜色的前景色和将要被去除掉的的背景色的分界线。同时设置处理后前景色和后景色的颜色,用以呈现最终的分割效果。


    threshold = 150
    bg_color = (255, 255, 255, 0)
    fg_color = (255, 0, 0, 255)
   
    if len(sys.argv) >= 2:
        path  = sys.argv[1]
    if len(sys.argv) == 3:
        threshold = int(sys.argv[2])
    if len(sys.argv) == 5:
        bg_color = tuple(sys.argv[3])
        fg_color = tuple(sys.argv[4])  在这一步中,如果阈值threshold设定不同数值,图片会呈现不同的二值分界效果,如下图:
DSC0002.jpg
  如果阈值过小,则图像中的斑马,会有部分颜色较浅的前景色,即灰色斑纹被误判成背景色而被滤除掉,从而造成前景图像轮廓的残缺。
  如果阈值过大,则与上述情况相反,会有背景色被误判成前景色,造成斑纹的边缘膨胀,视觉上看也类似膨胀的效果(虽然原理完全不同)。
  所以,选择一个合适的阈值,对图像的分割效果至关重要。而这一点,又是随着图像不同而变化的,阈值要适应图像内容。
  对于这个问题,可以尝试使用动态阈值,结合图像统计来实现自匹配,本文未涉及,有兴趣的童鞋可以自行尝试。
  
  2.将图片转换成可以做像素操作的二值像素集合,然后使用设定好的阈值threshold进行前景后景分割:


def Img2bin_arr(img, threshold):
    '''
    @将位图流转化为二维二值数组
    @param img: instance of Image
    @param threshold: 大小范围[0, 255]
    '''
    threshold = max(0, threshold)
    threshold = min(255, threshold)
   
    if img.mode != 'L':
        img = img.convert('L')
        
    width, height = img.size
    pix = img.load()
   
    get_val = lambda p: 255 if p >= threshold else 0
        
    return [[get_val(pix[w, h]) for w in xrange(width)] for h in xrange(height)]  
  

  3.将分割好的像素使用预先设定的颜色上色,然后将像素集合重新封装成图片格式,然后返回这个图片,用于保存或显示。

def bin_arr2Img(matrix, bg_color, fg_color):
    '''
    @将二维二值数组转化为位图流
    @param img: instance of Image
    @param bg_color: 背景色,元组类型,格式:(L)(灰度),(R, G, B),或者(R, G, B, A)
    @param fg_color: 前景色
    '''
    def ensure_color(color):
        if len(color) == 1:
            return (color, color, color, 255)
        elif len(color) == 3:
            color = list(color)
            color.append(255)
            return tuple(color)
        elif len(color) == 4:
            return color
        else:
            raise ValueError, 'len(color) cannot be %d' % len(color)
        
    bg_color = ensure_color(bg_color)
    fg_color = ensure_color(fg_color)
   
    height, width = len(matrix), len(matrix[0])
    dst_img = Image.new("RGBA", (width, height))
    dst_pix = dst_img.load()
   
    for w in xrange(width):
        for h in xrange(height):
            if matrix[h][w] < 128:
                dst_pix[w, h] = fg_color
            else:
                dst_pix[w, h] = bg_color
               
    return dst_img  总结:使用python进行像素级图像处理,同其他平台的像素处理类似,整个过程非常清晰,大体上都是三步,拆包-处理-封包。鉴于python的处理速度实在是不敢恭维,所以它是一个很好的算法效果验证平台。
  
  完整代码分享如下:

#start
# -*- coding: cp936 -*-
import Image

img = Image.open("1.jpg")

def Img2bin_arr(img, threshold):
    '''
    @将位图流转化为二维二值数组
    @param img: instance of Image
    @param threshold: 大小范围[0, 255]
    '''
    threshold = max(0, threshold)
    threshold = min(255, threshold)
   
    if img.mode != 'L':
        img = img.convert('L')
        
    width, height = img.size
    pix = img.load()
   
    get_val = lambda p: 255 if p >= threshold else 0
        
    return [[get_val(pix[w, h]) for w in xrange(width)] for h in xrange(height)]

def bin_arr2Img(matrix, bg_color, fg_color):
    '''
    @将二维二值数组转化为位图流
    @param img: instance of Image
    @param bg_color: 背景色,元组类型,格式:(L)(灰度),(R, G, B),或者(R, G, B, A)
    @param fg_color: 前景色
    '''
    def ensure_color(color):
        if len(color) == 1:
            return (color, color, color, 255)
        elif len(color) == 3:
            color = list(color)
            color.append(255)
            return tuple(color)
        elif len(color) == 4:
            return color
        else:
            raise ValueError, 'len(color) cannot be %d' % len(color)
        
    bg_color = ensure_color(bg_color)
    fg_color = ensure_color(fg_color)
   
    height, width = len(matrix), len(matrix[0])
    dst_img = Image.new("RGBA", (width, height))
    dst_pix = dst_img.load()
   
    for w in xrange(width):
        for h in xrange(height):
            if matrix[h][w] < 128:
                dst_pix[w, h] = fg_color
            else:
                dst_pix[w, h] = bg_color
               
    return dst_img

def paper_cut(img, threshold, bg_color, fg_color):
    '''
    @效果:剪纸
    @param img: instance of Image
    @param threshold: 大小范围[0, 255]
    @param bg_color: 背景色,元组类型,格式:(L)(灰度),(R, G, B),或者(R, G, B, A)
    @param fg_color: 前景色
    @return: instance of Image
    '''
    matrix = Img2bin_arr(img, threshold) # 位图转化为二维二值数组
    return bin_arr2Img(matrix, bg_color, fg_color) # 二维二值数组转化为位图

if __name__ == "__main__":
    import sys, os, time

    path = os.path.dirname(__file__) + os.sep.join(['', '1.jpg'])
    threshold = 150
    bg_color = (255, 255, 255, 0)
    fg_color = (255, 0, 0, 255)
   
    if len(sys.argv) >= 2:
        path  = sys.argv[1]
    if len(sys.argv) == 3:
        threshold = int(sys.argv[2])
    if len(sys.argv) == 5:
        bg_color = tuple(sys.argv[3])
        fg_color = tuple(sys.argv[4])

    start = time.time()
   
    img = Image.open(path)
    img = paper_cut(img, threshold, bg_color, fg_color)
    img.save(os.path.splitext(path)[0]+'.papercut_'+str(threshold)+'.png', 'PNG')

    end = time.time()
    print 'It all spends %f seconds time' % (end-start)

#end
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-144780-1-1.html 上篇帖子: MySQL通用批量写入工具(Python) 下篇帖子: 【实用】如何将sublime text 3 打造成实用的python IDE 环境
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表