文章目录

  • 绘制直方图
  • 1.矩阵扁平化
  • 2.plt.hist()
  • 3.绘制原图的等高线
  • 4.彩色图片直方图
  • 直方图均衡化
  • 1.np.histogram()
  • 2.均衡化
  • 3.调用cv2.equalizeHist()
  • 4.彩色图直方图均衡化


绘制直方图

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
im = np.array(Image.open('lina2.png').convert('L'))
plt.hist(im.flatten(),255)
plt.show()

promethues直方图 prism做直方图_python

1.矩阵扁平化

注意:要将像素矩阵扁平化
220行220列变成一行48400列

b=im.flatten()

promethues直方图 prism做直方图_直方图_02

2.plt.hist()

bins是柱子的数目
其他具体参数:


n, bins, patches = plt.hist(arr, bins=50, normed=1, facecolor=‘green’, alpha=0.75)
hist的参数非常多,但常用的就这五个,只有第一个是必须的,后面四个可选
arr: 需要计算直方图的一维数组
bins: 直方图的柱数,可选项,默认为10
normed: 是否将得到的直方图向量归一化。默认为0 现在好像改成了density
facecolor: 直方图颜色
alpha: 透明度
返回值 :
n: 直方图向量,是否归一化由参数设定
bins: 返回各个bin的区间范围
patches: 返回每个bin里面包含的数据,是一个list

没有归一化的

plt.hist(im.flatten(),bins=10,color='y',range=(100,200))
Out[5]: 
(array([3175., 2690., 3897., 3903., 4223., 4622., 2712., 2226., 1292.,
        1735.]),
 array([100., 110., 120., 130., 140., 150., 160., 170., 180., 190., 200.]),
 <a list of 10 Patch objects>)

promethues直方图 prism做直方图_numpy_03


归一化的:

n, bins, patches = plt.hist(im.flatten(), bins=255, density=1)

promethues直方图 prism做直方图_python_04


看看返回值是什么:n: 直方图向量,是否归一化由参数设定,就是每个柱子高度

promethues直方图 prism做直方图_直方图_05


bins: 返回各个bin的区间范围

promethues直方图 prism做直方图_numpy_06


patches: 返回每个bin里面包含的数据,是一个list(n和bins两个返回值的合并)

promethues直方图 prism做直方图_numpy_07

3.绘制原图的等高线

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
# read image to array
im = np.array(Image.open('lina2.png').convert('L'))
# create a new figure
plt.subplot(1,3,1)
plt.imshow(im)
 # don’t use colors
plt.subplot(1,3,2);plt.gray()
# show contours with origin upper left corner
#在Lina图上绘制等高线
plt.contour(im, origin='image')
plt.axis('equal')
plt.axis('off')
plt.subplot(133)
# #注意要将图像扁平化
plt.hist(im.flatten(),255)
plt.show()

promethues直方图 prism做直方图_numpy_08

4.彩色图片直方图

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("lina2.png",1)
(b, g, r) = cv2.split(img)
plt.figure("lena")
ar=np.array(r).flatten()
plt.hist(ar, bins=256, density=1,facecolor='r',edgecolor='r')
ag=np.array(g).flatten()
plt.hist(ag, bins=256, density=1, facecolor='g',edgecolor='g')
ab=np.array(b).flatten()
plt.hist(ab, bins=256, density=1, facecolor='b',edgecolor='b')
plt.show()

promethues直方图 prism做直方图_promethues直方图_09

直方图均衡化

1.np.histogram()

用法与plt.hist类似

imhist, bins = np.histogram(im, 255, density=True)

矩阵不用flatten()了,得到的结果imhist与上述plt.hist的返回值n是一样的

promethues直方图 prism做直方图_promethues直方图_10

2.均衡化

-*- coding: utf-8 -*-
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import cv2

plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False

def histeq(im, nbr_bins=256):
    # 对一副灰度图像进行直方图均衡化
    # 该函数有两个输入参数,一个是灰度图像,一个是直方图中使用小区间的数目
    # 函数返回直方图均衡化后的图像,以及用来做像素值映射的累计分布函数
    # 计算图像的直方图

    imhist, bins =np.histogram(im.flatten(), nbr_bins, normed=True)
    cdf = imhist.cumsum()  # cumulative distribution function最后一个值接近于1,可以近似为1
    cdf = 255 * cdf / cdf[-1]  # 归一化,函数中使用累计分布函数的最后一个元素(下标为-1,目标是
    # 将其归一化到0-1范围 )
    # 使用累计分布函数的线性插值,计算新的像素值
    im2 = np.interp(im.flatten(), bins[:-1], cdf)  # im2 is an array
    return im2.reshape(im.shape), cdf

im = np.array(Image.open('lina2.png').convert('L'))
im2, cdf = histeq(im)
im20 = Image.fromarray(im)  # 未直方图均衡化的图像
im21 = Image.fromarray(im2)  # 直方图均衡化后的 将array转化为图像

plt.figure(num='lina')
plt.subplot(2, 2, 1)
plt.title("Before the experiment");plt.axis('off')
plt.imshow(im, plt.cm.gray)

plt.subplot(2,2,2)
plt.hist(im.flatten(),255)
plt.title("未均衡化的直方图");plt.axis('off')

plt.subplot(2, 2, 3)
plt.title("After the experiment") ; plt.axis('off')
plt.imshow(im2, plt.cm.gray)

plt.subplot(2, 2, 4)
plt.title("均衡化后的直方图") ; plt.axis('off')
plt.hist(im2.flatten(),255)
plt.show()

promethues直方图 prism做直方图_直方图_11


promethues直方图 prism做直方图_opencv_12

3.调用cv2.equalizeHist()

但是cv2.equalizeHist()只提供灰度值图片的处理

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import cv2

lina=cv2.imread('lina2.png',0)
dst = cv2.equalizeHist(lina)
plt.subplot(223);plt.imshow(dst,'gray');plt.title('after')
plt.subplot(224);plt.hist(dst.flatten(),255)
plt.subplot(221);plt.imshow(lina,'gray');plt.title('before')
plt.subplot(222);plt.hist(lina.flatten(),255)
plt.show()

promethues直方图 prism做直方图_python_13

4.彩色图直方图均衡化

#彩色直方图均衡化
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("lina2.png",1)
cv2.imshow("src", img)

# 彩色图像均衡化,需要分解通道 对每一个通道均衡化
(b, g, r) = cv2.split(img)
bH = cv2.equalizeHist(b)
gH = cv2.equalizeHist(g)
rH = cv2.equalizeHist(r)
# 合并每一个通道
result = cv2.merge((bH, gH, rH))
cv2.imshow("dst", result)
cv2.waitKey(0)

promethues直方图 prism做直方图_直方图_14


颜色发生畸变

采用以下方式

https://www.jianshu.com/p/9a9000d226b6

import numpy as np
import cv2


def hisEqulColor(img):
    ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCR_CB)
    channels = cv2.split(ycrcb)
    print (len(channels))
    cv2.equalizeHist(channels[0], channels[0])
    cv2.merge(channels, ycrcb)
    cv2.cvtColor(ycrcb, cv2.COLOR_YCR_CB2BGR, img)
    return img

im = cv2.imread('lina2.png')
cv2.imshow('im1', im)
cv2.waitKey(0)

eq = hisEqulColor(im)
cv2.imshow('image2',eq )
cv2.waitKey(0)
cv2.imwrite('lena2.jpg',eq)

promethues直方图 prism做直方图_直方图_15

5.YUV 直方图均衡化

import cv2
import numpy as np
img = cv2.imread("lina2.png", 1)

imgYUV = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
cv2.imshow("src", img)

channelsYUV = cv2.split(imgYUV)
channelsYUV[0] = cv2.equalizeHist(channelsYUV[0])

channels = cv2.merge(channelsYUV)
result = cv2.cvtColor(channels, cv2.COLOR_YCrCb2BGR)
cv2.imshow("dst", result)

cv2.waitKey(0)

promethues直方图 prism做直方图_opencv_16