python画图片的直方图_【编程】用Python修图是怎样一种体验?

前些天学习了Python图像处理库PIL(Python Imaging Library),觉得十分有趣,对于Photoshop的图像处理过程似乎有了新的见解,稍稍记录一下。

       想到之前还有好多照片没有处理,这里特别选了一张[新疆那拉提]的照片来试试水。

1. 导入相关库

from PIL import Image

from pylab import *

import matplotlib.pyplot as plt

import numpy as np

from matplotlib.font_manager import FontProperties

font = FontProperties(fname = r"C:\Windows\Fonts\Simsun.ttc",size=14)

2. 读取并查看图片

img=Image.open("./img/xj/green_1.jpg")

print(img.mode, img.size, img.format)

img_array=array(img)

print(img_array.shape)

figure(figsize=(12,5))

subplot(121)

axis('off')

imshow(img)

title(u'原图',fontproperties=font)

subplot(122)

title(u'原图直方图',fontproperties=font)

ax=gca()

ax.yaxis.get_major_formatter().set_powerlimits((0,1))

hist(img_array.flatten())

RGB (6000, 3376) JPEG (3376, 6000, 3)

9b9cf682040cfc5c2485d8713ffec786.png

       这张图片是6000x3376像素,有三个通道的JPEG格式。

3. 分通道查看

       此处列出2个通道,其他依次类推。

subplot(231)

title(u'R通道',fontproperties=font)

ax=gca()

ax.yaxis.get_major_formatter().set_powerlimits((0,1))

hist(img_array[:,:,0].flatten())

subplot(232)

title(u'G通道',fontproperties=font)

ax=gca()

ax.yaxis.get_major_formatter().set_powerlimits((0,1))

hist(img_array[:,:,1].flatten())

61ad459af555d3952992f851fedba200.png

       可以看出由于背光拍摄,这张图片的山体部分有些曝光不足。 我们可以试试把图片直方图均衡化看看效果如何。

4、图像调整

def equalization(img_array):

img_shape=img_array.shape

img2=np.zeros(shape=img_shape)

for p in range(3):

imhist,bins = histogram(img_array[:,:,p].flatten(),256)

cdf = imhist.cumsum() # 累积分布函数

cdf = 255 * cdf / cdf[-1] # 归一化

temp = interp(img_array[:,:,p].flatten(),bins[:-1],cdf)

img2[:,:,p] = np.reshape(temp,img_shape[:2])

img2=img2.astype(int)

return img2

然后我们就可以看到图片被处理成了这样子:

5031ddd1f57860013c521896aeb9961c.png

        它的三个通道的像素值都被均衡调整了一下。

cc16d564b74d35e6b7385ba36641b0b9.png

       中间到底发生了什么呢?   

       我们把累计分布函数画出来看看。

f47e5a1c7bd62dd76736260ce5de1668.png

       其实,均衡化就是通过计算图各像素的像素值的分布,根据总体的情况进行调整。在我们的图片中,由于暗部较多,低像素值的像素数应该会比较多,这点可以从上图的曲线中也可以看出来。这样就会造成我们的曲线变成凸形的,在采用interp()进行插值时,低像素值的像素点就会被提高,也即是从我们图中的橙色线上移至蓝色线。这跟Photoshop里面利用曲线进行调整的道理类似。

       可以推出,当我们图片亮部较多时,这个蓝色线会变成陡峭上升的形态,也即是会低于橙色线,这时采用上面的方法将会把图片整体压暗。

       回来重新审视我们这张图,其实亮部没有问题,不需要调整。我们试试画一条曲线来直接调整暗部。

x1 = np.array([ 0, 32, 64, 96, 128, 160, 192, 224, 255])

y1 = np.array([ 30, 60, 100, 130, 150, 165, 200, 225, 250])

z1 = np.polyfit(x1, y1, 3)#用3次多项式拟合

p1 = np.poly1d(z1)

yvals=p1(x1)

figure(figsize=(5,5))

plot1=plt.plot(x1, y1, '*',label='original values')

plot2=plt.plot(x1, yvals, 'r',label='polyfit values')

plot(x,y,":")

plt.legend(loc=4)

axis([0,255,0,255])

       我绘制了这样一条曲线:

9d07f09807acd517097d2220cd640a89.png

def test1(img_array,curve):

img_shape=img_array.shape

img2=np.zeros(shape=img_shape)

xp=np.arange(0,256,1)

fp=curve(xp)

for p in range(3):

temp = interp(img_array[:,:,p].flatten(),xp,fp)

img2[:,:,p] = np.reshape(temp,img_shape[:2])

img2=img2.astype(int)

return img2

556af2a28a7fd398864d430a4e3fc002.png

       到这里我们就完成了一张图片曝光的粗略调整,相信进一步地可以实现很多PS里面的功能,应该也可以做出来一些滤镜。本人对PS各个功能的算法颇有兴趣,如果有小伙伴有什么创意或见解的话,欢迎在下面评论告诉我哦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值