第1关:灰度直方图的计算
100
- 任务要求
- 参考答案
- 重置记录
- 评论
- 关卡排行榜
任务描述
本关任务:编写一个能计算数字图像直方图的小程序,并且输出图像的最大和最小像素值。
相关知识
为了完成本关任务,你需要掌握:
- 认识灰度直方图
- 数字图像的读取;
- 灰度直方图计算
- 输出直方图。
认识灰度直方图
什么是灰度直方图?
灰度级范围[0,L−1]
的数字直方图是离散函数h(rk)=nk
,其中rk
是第k
极灰度值, nk
是图像中灰度为rk
的像素个数。在实践中,经常用乘积MN
表示的图像像素的总数除以每个分量的个数来归一化直方图(M和N代表一张图的行和列)。因此,归一化的直方图由p(rk)=nk/MN
给出,其中k=0,1,...,L−1
。所以归一化后的直方图所有分量和应该为1.
总结来说,直方图可以表示特定灰度值的像素个数,归一化后的直方图表示特定灰度值在一张图中出现概率。
数字图像的读取
数字图像读取
通常数字图像的读取有很多种方式,在python程序设计中我简单介绍2
种数字图像的读取方式。
在这里我们先给定图片的路径。
img_path='histogram/data/girl.jpg'
1,OpenCV读取的图片
OpenCV库读取图像直接转为就是numpy.ndarray格式,无需转换。
import sys
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
#定义数据路径
img_path='histogram/data/girl.jpg'
#用cv2的标准库函数imread()进行读入数据路径
im_arr=cv.imread(img_path)
print(np.shape(im_arr))
输出: (888, 888, 3)
2,PIL读取图片
PIL读取的图片并不是直接的numpy.ndarray格式,需要进行转换
import sys
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
#定义图像路径
img_path='histogram/data/girl.jpg'
#用PIL中的Image()方法读入数据路径
img_PIL = Image.open(datapath)#读取数据
#打印查看得到未经转化的数据和数据类型
print("img_PIL:",img_PIL)
print("img_PIL:",type(img_PIL))
#经过np.array()方法后得到的img_PIL的数组矩阵,查看矩阵大小和类型
img_PIL = np.array(img_PIL)
print("img_PIL:",img_PIL.shape)
print("img_PIL:",type(img_PIL))
输出:
img_PIL: <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=888x888 at 0x2D198B00080>
img_PIL: <class 'PIL.JpegImagePlugin.JpegImageFile'>
img_PIL: (888, 888, 3)
img_PIL: <class 'numpy.ndarray'>
图像转为灰度图
利用openCV库函数可以将彩色图片转为灰度图片。
import cv2
import numpy as np
if __name__ == "__main__":
img_path = 'histogram/data/girl.jpg'
img = cv2.imread(img_path) #获取图片的宽和高
width,height = img.shape[:2][::-1]
#将图片缩小便于显示观看
img_resize = cv2.resize(img,(int(width*0.5),int(height*0.5)),interpolation=cv2.INTER_CUBIC)
cv2.imshow("img",img_resize)
print("img_reisze shape:{}".format(np.shape(img_resize)))
#将图片转为灰度图
img_gray = cv2.cvtColor(img_resize,cv2.COLOR_RGB2GRAY)
cv2.imshow("img_gray",img_gray)
print("img_gray shape:{}".format(np.shape(img_gray)))
cv2.waitKey()
输出:
图 1 彩色图转为灰度图
灰度直方图的计算函数
下面简单的介绍计算灰度直方图的函数。
Python函数:
def calcHist(images, channels, mask, histSize, ranges, hist=None, accumulate=None):
images:必须用方括号括起来。 channels:是用于计算直方图的通道,这里使用灰度图计算直方图,所以就直接使用第一个通道;Mask:这里没有使用,所以用None。 histSize:表示这个直方图分成多少份(即多少个直方柱)accumulate:表示直方图中各个像素的值,[0.0, 256.0]表示直方图能表示像素值从0.0到256的像素。
输出灰度直方图
在这里我们还是以小女孩的图片为例,进行灰度图像直方图的绘制。
img_path = 'histogram/data/girl.jpg'
计算直方图函数,img参数为输入图像,img_plt为生成图像灰度直方图
def histCover(img, fileName):
plt.figure(fileName, figsize=(16, 8))
# 展示输入图像
plt.subplot(121)
plt.imshow(img, "gray")
# 展示直方图
plt.subplot(122)
# 利用cv2内置函数进行画灰度图像直方图
hist = cv2.calcHist([img], [0], None, [256], [0, 255])
print('max:',max(hist))
print('min:',min(hist))
plt.plot(hist)
plt.xlim([0, 255])
plt.show()
输出结果和图像:
max: [162271.]
min: [0.]
图 2 灰度图像直方图的绘制
编程要求
根据提示,在右侧编辑器补充代码,学会灰度图像直方图的绘制,在这里我们还是以卡通图片为例子,输出其直方图的峰值和最小值(打印输出时要记得换行)。
应用matplotlib.pyplot()函数可能不能进行图片展示(可以应用imsaveifg(filename)函数进行临时保存到编译环境),但是也可以在本地环境中运行输出图片,但是一定要有matplotlib库,如果没有该库函数,图片不能进行展示,可以在本地python环境中安装,应用
pip install matplotlib
指令进行安装和配置。
测试说明
平台会对你编写的代码进行测试:
直方图的峰值(最大值)和最小值是编程评测的重点,因为一副图像只唯一对应一副直方图,因此峰值(最大值)和最小值是唯一被确定的。
打印输出记得换行操作。
格式: 预期输出: max: [10199.]
min: [0.]
开始你的任务吧,祝你成功!
"""
本次实训任务为对灰度图像进行直方图的计算,以卡通图片为例,你需要首先将彩色图像转化为灰度图(这是必须要掌握的一个重点),
再进行计算和绘制直方图,在这里考核的重点是对直方图的峰值(最大值)和最小值的输出,因为一副图像可以唯一确定一副直方图,
该直方图的峰值(最大值)和最小值也是唯一被确定的。所以根据提示,完善相应代码,相信你一定可以的。
"""
import sys
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
#计算直方图函数,img参数为输入图像,img_plt为生成图像灰度直方图
def histCover(img, fileName):
plt.figure(fileName, figsize=(16, 8))
# 展示输入图像
plt.subplot(121)
plt.imshow(img, "gray")
# 展示直方图
plt.subplot(122)
"""
任务1 利用cv.calcHist()内置函数进行画灰度图像直方图,该函数的返回值是hist
"""
########## Begin ##########
hist = cv.calcHist([img], [0], None, [256], [0, 255])
########## End ##########
print('max:',max(hist))
print('min:',min(hist))
plt.plot(hist)
plt.xlim([0, 255])
plt.savefig(fileName)
plt.show()
#主函数的定义,定义图片路径
def main_func(argv):
img_path = 'histogram/step3/img_data/ex_1.jpg'
img_plt='histogram/step3/stu_img/step3_plt.jpg'
"""
任务2. 读入图像,并转化为灰度值,数据路径已经给出为img_path
"""
########## Begin ##########
img_PIL = Image.open(img_path)
img_array = np.array(img_PIL)
img_gray = cv.cvtColor(img_array,cv.COLOR_RGB2GRAY)
########## End ##########
"""
任务3. 调用histCover函数绘制直方图,看清楚该函数是无返回值的哦
"""
########## Begin ##########
histCover(img_gray, img_plt)
########## End ##########
if __name__ == '__main__':
main_func(sys.argv)