第1关:灰度直方图的计算

第1关:灰度直方图的计算

100

  • 任务要求
  • 参考答案
  • 重置记录
  • 评论
  • 关卡排行榜

任务描述

本关任务:编写一个能计算数字图像直方图的小程序,并且输出图像的最大和最小像素值。

相关知识

为了完成本关任务,你需要掌握:

  1. 认识灰度直方图
  2. 数字图像的读取;
  3. 灰度直方图计算
  4. 输出直方图。
认识灰度直方图

什么是灰度直方图?

灰度级范围[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种数字图像的读取方式。

在这里我们先给定图片的路径。

 
  1. img_path='histogram/data/girl.jpg'

1,OpenCV读取的图片

OpenCV库读取图像直接转为就是numpy.ndarray格式,无需转换。

 
  1. import sys
  2. import cv2 as cv
  3. import matplotlib.pyplot as plt
  4. import numpy as np
  5. from PIL import Image
  6. #定义数据路径
  7. img_path='histogram/data/girl.jpg'
  8. #用cv2的标准库函数imread()进行读入数据路径
  9. im_arr=cv.imread(img_path)
  10. print(np.shape(im_arr))

输出(888, 888, 3)

2,PIL读取图片

PIL读取的图片并不是直接的numpy.ndarray格式,需要进行转换

 
  1. import sys
  2. import cv2 as cv
  3. import matplotlib.pyplot as plt
  4. import numpy as np
  5. from PIL import Image
  6. #定义图像路径
  7. img_path='histogram/data/girl.jpg'
  8. #用PIL中的Image()方法读入数据路径
  9. img_PIL = Image.open(datapath)#读取数据
  10. #打印查看得到未经转化的数据和数据类型
  11. print("img_PIL:",img_PIL)
  12. print("img_PIL:",type(img_PIL))
  13. #经过np.array()方法后得到的img_PIL的数组矩阵,查看矩阵大小和类型
  14. img_PIL = np.array(img_PIL)
  15. print("img_PIL:",img_PIL.shape)
  16. print("img_PIL:",type(img_PIL))

输出

 
  1. img_PIL: <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=888x888 at 0x2D198B00080>
  2. img_PIL: <class 'PIL.JpegImagePlugin.JpegImageFile'>
  3. img_PIL: (888, 888, 3)
  4. img_PIL: <class 'numpy.ndarray'>
图像转为灰度图

利用openCV库函数可以将彩色图片转为灰度图片。

 
  1. import cv2
  2. import numpy as np
  3. if __name__ == "__main__":
  4. img_path = 'histogram/data/girl.jpg'
  5. img = cv2.imread(img_path) #获取图片的宽和高
  6. width,height = img.shape[:2][::-1]
  7. #将图片缩小便于显示观看
  8. img_resize = cv2.resize(img,(int(width*0.5),int(height*0.5)),interpolation=cv2.INTER_CUBIC)
  9. cv2.imshow("img",img_resize)
  10. print("img_reisze shape:{}".format(np.shape(img_resize)))
  11. #将图片转为灰度图
  12. img_gray = cv2.cvtColor(img_resize,cv2.COLOR_RGB2GRAY)
  13. cv2.imshow("img_gray",img_gray)
  14. print("img_gray shape:{}".format(np.shape(img_gray)))
  15. cv2.waitKey()

输出:

图 1


图 1 彩色图转为灰度图

灰度直方图的计算函数

下面简单的介绍计算灰度直方图的函数。

Python函数:

 
  1. def calcHist(images, channels, mask, histSize, ranges, hist=None, accumulate=None):

images:必须用方括号括起来。 channels:是用于计算直方图的通道,这里使用灰度图计算直方图,所以就直接使用第一个通道;Mask:这里没有使用,所以用None。 histSize:表示这个直方图分成多少份(即多少个直方柱)accumulate:表示直方图中各个像素的值,[0.0, 256.0]表示直方图能表示像素值从0.0到256的像素。

输出灰度直方图

在这里我们还是以小女孩的图片为例,进行灰度图像直方图的绘制。

 
  1. img_path = 'histogram/data/girl.jpg'

计算直方图函数,img参数为输入图像,img_plt为生成图像灰度直方图

 
  1. def histCover(img, fileName):
  2. plt.figure(fileName, figsize=(16, 8))
  3. # 展示输入图像
  4. plt.subplot(121)
  5. plt.imshow(img, "gray")
  6. # 展示直方图
  7. plt.subplot(122)
  8. # 利用cv2内置函数进行画灰度图像直方图
  9. hist = cv2.calcHist([img], [0], None, [256], [0, 255])
  10. print('max:',max(hist))
  11. print('min:',min(hist))
  12. plt.plot(hist)
  13. plt.xlim([0, 255])
  14. plt.show()

输出结果和图像

max: [162271.] min: [0.]

图 1


图 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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值