OpenCV—python 颜色空间(RGB,HSV,Lab)与 颜色直方图

一、图像分类的过程

image.png
  1. 图片必须经过标注
    图片的类别为有限的集合,如{猫、狗、牛、马、狼}
    每个类别的图片数量接近,如果不同类别图片的数量差异很大,训练出来的分类器容易倾向于图片数量多的类别

  2. 划分训练/测试集
    在训练之前,要把数据集划分为训练集(学习分类器)和测试集(对分类器进行评估)
    训练集和测试集相互独立,不重合!

3.特征表示 :对图片进行数值处理,转换成计算机可理解的特征,常用特征:

  • 颜色直方图(Color Histograms)
  • 方向梯度直方图(Histogram of Oriented Gradients,HOG)
  • 局部二值模式(Local Binary Pattern,LBP)
  1. 分类算法 :一般分类算法即可:逻辑回归,支持向量机(SVM),随机森林

  2. 模型评估 : 混淆矩阵(Confusion Matrix)

  • 精确度(Precision)
  • 召回率(Recall)
  • F1值(F1 score) recall与Precision的调和均值

二、开发环境:(安装)OpenCV 计算机视觉库

安装:
方法1:conda install -c menpo opencv 
方法2:conda install --channel https://conda.anaconda.org/menpo opencv3 
方法3:pip/conda install opencv-python
方法4:使用 whl 文件进行安装,进入网站 http://www.lfd.uci.edu/~gohlke/pythonlibs/。 
      下载与当前环境兼容的 opencv 文件。切换到该文件所在的目录,在命令行环境下使用 
      例如:安装文件:opencv_python-3.2.0-cp35-cp35m-win_amd64.whl
      pip install opencv_python-3.2.0-cp35-cp35m-win_amd64.whl

opencv 的导入: 
import cv2
cv2.__version__
    
    OpenCV的使用
        在线文档:http://docs.opencv.org/2.4.11/

三、颜色空间(颜色模型:RGB,HSV,Lab)

RGB颜色空间有:
RGB :模型容易理解,连续变换颜色时不直观
(红red 绿green 蓝blue)三原色:取值范围都是:[0,255],[0,255],[0,255]

HSV: 是为了数字化图像提出来了,不能很好的表示人眼解释图像过程

  • H (Hue)色相:[0,360]
  • S (Saturation)饱和度,即色彩纯净度,0饱和度为白色
  • V (Value/Brightness):明度 0明度为纯黑色

在OpenCV中,颜色范围:

  • H = [0,179]
  • S = [0,255]
  • V = [0,255]

Lab:颜色之间的欧式距离有具体含义–距离越大,人眼感官两种颜色差距越远

  • L 通道:像素亮度,上白下黑 中间灰
  • a 通道:左绿 右红
  • b 通道:一端纯蓝,一端纯黄

灰度图:每个像素[0,255]
根据人眼敏感度,把RGB图片转换为灰度图,不是简单把RGB每个通道取平均值
而是:Y = 0.299R + 0.587G + 0.114*B

image.png

3.1 opencv–HSV颜色空间

HSV(hue,saturation,value)颜色空间的模型对应于圆柱坐标系中的一个圆锥形子集,圆锥的顶面对应于V=1. 它包含RGB模型中的R=1,G=1,B=1 三个面,所代表的颜色较亮。
色彩H由绕V轴的旋转角给定。红色对应于 角度0° ,绿色对应于角度120°,蓝色对应于角度240°。

在HSV颜色模型中,每一种颜色和它的补色相差180° 。 饱和度S取值从0到1,所以圆锥顶面的半径为1。
在圆锥的顶点(即原点)处V=0,H和S无定义, 代表黑色。
圆锥的顶面中心处 S=0,V=1,H无定义,代表白色。
从该点到原点代表亮度渐暗的灰色,即具有不同 灰度的灰色。
对于这些点,S=0,H的值无定义。可以说,HSV模型中的V轴对应于RGB颜色空间中的主对角线。 在圆锥顶面的圆周上的颜色,V=1,S=1,这种颜色是纯色。

HSV颜色空间它锥形的钻换模型中可以理解到: hue 通道的取值范围就应该是 0-360度,单数在opencv中其取值范围 [0,180]。


image.png

在opencv-hsv取值详情如下:


image.png

颜色库:


image.png

image.png

原本输出的 HSV 的取值范围分别是 0-360, 0-1, 0-1;但是为了匹配目标数据类型 OpenCV 将每个通道的取值范围都做了修改,于是就变成了 0-180, 0-255, 0-255,并且同时解释道:为了适应 8bit 0-255 的取值范围,将 hue 通道 0-360 的取值范围做了减半处理

四、OpenCV处理图片

4.1 直接读取图片

import cv2                      #导入 Opencv
import os 
import numpy as np
import matplotlib.pyplot as plt


output_dir = 'output2'          #设置输出文件夹,若不存在则创建
if not os.path.exists(output_dir):
    os.mkdir(output_dir)    

img_file = './../image.png'     #读取图片
img = cv2.imread(img_file)

type(img)                       #读入图片后得到ndarray 对象
img.shape                       #ndarray的三个维度分别是图片的:高,宽,通道

# pyplot.imgshow 在显示图片时是按照RGB通道顺序显示,cv2则相反
# 需要通过 np.flip(img,axis = 2) 调整3个通道的顺序(若不调整图片颜色失真)
plt.imshow(np.flip(img,axis = 2))
plt.axis('off')
plt.show()                      #图1

plt.imshow(img)
plt.axis('off')                 #不显示坐标
plt.show()                      #图2

#输出并保存图片
output_image = os.path.join(output_dir,'image.png')
cv2.imwrite(output_image,img)
image.png

4.2 读取图片并简单处理—图像特征:颜色直方图

OpenCV-Python中调用的直方图计算函数为cv2.calcHist。

"""
hist = cv2.calcHist([image],             # 传入图像(列表)
                    [0],                 # 使用的通道(使用通道:可选[0],[1],[2])
                    None,                # 没有使用mask(蒙版)
                    [256],               # HistSize
                    [0.0,255.0])         # 直方图柱的范围
                                         # return->list
"""

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

def calcAndDrawHist(image, color):  
    hist= cv2.calcHist([image], [0], None, [256], [0.0,255.0])  
    minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(hist)  
    histImg = np.zeros([256,256,3], np.uint8)  
    hpt = int(0.9* 256);  
      
    for h in range(256):  
        intensity = int(hist[h]*hpt/maxVal)  
        cv2.line(histImg,(h,256), (h,256-intensity), color)  
    return histImg


if __name__ == '__main__':  
    original_img = cv2.imread("666.png")
    img = cv2.resize(original_img,None,fx=0.6,fy=0.6,interpolation = cv2.INTER_CUBIC)
    b, g, r = cv2.split(img)  
  
    histImgB = calcAndDrawHist(b, [255, 0, 0])  
    histImgG = calcAndDrawHist(g, [0, 255, 0])  
    histImgR = calcAndDrawHist(r, [0, 0, 255])  

    cv2.imshow("histImgB", histImgB)  
    cv2.imshow("histImgG", histImgG)  
    cv2.imshow("histImgR", histImgR)  
    cv2.imshow("Img", img)  
    cv2.waitKey(0)  
    cv2.destroyAllWindows() 

image.png

颜色空间 RGB–HSV–Lab
RGB颜色空间

import cv2
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline 

pic_file = '../data/images/image_crocus_0003.png'

img_bgr = cv2.imread(pic_file, cv2.IMREAD_COLOR) #OpenCV读取颜色顺序:BGR 
img_b = img_bgr[..., 0]
img_g = img_bgr[..., 1]
img_r = img_bgr[..., 2]
fig = plt.gcf()                                  #图片详细信息


fig = plt.gcf()                                  #分通道显示图片
fig.set_size_inches(10, 15)

plt.subplot(221)
plt.imshow(np.flip(img_bgr, axis=2))             #展平图像数组并显示
plt.axis('off')
plt.title('Image')

plt.subplot(222)
plt.imshow(img_r, cmap='gray')
plt.axis('off')
plt.title('R')

plt.subplot(223)
plt.imshow(img_g, cmap='gray')
plt.axis('off')
plt.title('G')

plt.subplot(224)
plt.imshow(img_b, cmap='gray')
plt.axis('off')
plt.title('B')

plt.show()

image.png

HSV颜色空间

img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)
img_h = img_hsv[..., 0]
img_s = img_hsv[..., 1]
img_v = img_hsv[..., 2]

fig = plt.gcf()                      # 分通道显示图片
fig.set_size_inches(10, 15)

plt.subplot(221)
plt.imshow(img_hsv)
plt.axis('off')
plt.title('HSV')

plt.subplot(222)
plt.imshow(img_h, cmap='gray')
plt.axis('off')
plt.title('H')

plt.subplot(223)
plt.imshow(img_s, cmap='gray')
plt.axis('off')
plt.title('S')

plt.subplot(224)
plt.imshow(img_v, cmap='gray')
plt.axis('off')
plt.title('V')

plt.show()
image.png

Lab*颜色空间

img_lab = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2LAB)
img_ls = img_lab[..., 0]
img_as = img_lab[..., 1]
img_bs = img_lab[..., 2] 

# 分通道显示图片
fig = plt.gcf()
fig.set_size_inches(10, 15)

plt.subplot(221)
plt.imshow(img_lab)
plt.axis('off')
plt.title('L*a*b*')

plt.subplot(222)
plt.imshow(img_ls, cmap='gray')
plt.axis('off')
plt.title('L*')

plt.subplot(223)
plt.imshow(img_as, cmap='gray')
plt.axis('off')
plt.title('a*')

plt.subplot(224)
plt.imshow(img_bs, cmap='gray')
plt.axis('off')
plt.title('b*')

plt.show()  

image.png

灰度图与其颜色直方图

img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
fig = plt.gcf()
fig.set_size_inches(5, 7.5)

plt.imshow(img_gray, cmap='gray')
plt.axis('off')
plt.title('Gray')
plt.show()
"""
    cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]]) → hist
    参数说明
    images:   图片列表
    channels: 需要计算直方图的通道。[0]表示计算通道0的直方图,[0,1,2]表示计算通道0,1,2所表示颜色的直方图
    mask:     蒙版,只计算值>0的位置上像素的颜色直方图,取None表示无蒙版
    histSize: 每个维度上直方图的大小,[8]表示把通道0的颜色取值等分为8份后计算直方图
    ranges:   每个维度的取值范围,[lower0, upper0, lower1, upper1, ...],lower可以取到,upper无法取到
    hist:     保存结果的ndarray对象
    accumulate: 是否累积,如果设置了这个值,hist不会被清零,直方图结果直接累积到hist中
""" 

img_gray_hist = cv2.calcHist([img_gray], [0], None, [256], [0, 256])

plt.plot(img_gray_hist)
plt.title('Grayscale Histogram')
plt.xlabel('Bins')
plt.ylabel('# of Pixels')
plt.show()
image.png

带蒙版的颜色直方图

# 读取模板
mask_file = '../data/masks/mask_crocus_0003.png'
mask = cv2.imread(mask_file, cv2.IMREAD_UNCHANGED) 
help(cv2.calcHist)
img_gray_hist_with_mask = cv2.calcHist([img_gray], [0], mask, [256], [0, 256])
"""
    图片按位与
    cv2.bitwise_and(src1, src2[, dst[, mask]]) → dst
    参数说明
        src1: 图片1
        src2: 图片2
        dst: 保存结果的ndarray对象
        mask: 蒙版 
"""
img_masked = cv2.bitwise_and(img_gray, img_gray, mask=mask)

plt.imshow(img_masked, cmap='gray')
plt.axis('off')
plt.title('Image with mask')
plt.show()

plt.plot(img_gray_hist_with_mask)
plt.title('Grayscale Histogram')
plt.xlabel('Bins')
plt.ylabel('# of Pixels')

plt.show()
image.png

多个颜色直方图

# 按R、G、B三个通道分别计算颜色直方图
b_hist = cv2.calcHist([img_bgr], [0], None, [256], [0, 256])
g_hist = cv2.calcHist([img_bgr], [1], None, [256], [0, 256])
r_hist = cv2.calcHist([img_bgr], [2], None, [256], [0, 256])

# 显示3个通道的颜色直方图
plt.plot(b_hist, label='B', color='blue')
plt.plot(g_hist, label='G', color='green')
plt.plot(r_hist, label='R', color='red')
plt.legend(loc='best')
plt.xlim([0, 256])
plt.show()

# 显示3个通道的颜色直方图
plt.plot(b_hist, label='B', color='blue')
plt.plot(g_hist, label='G', color='green')
plt.plot(r_hist, label='R', color='red')
plt.legend(loc='best')
plt.xlim([0, 256])
plt.show()
image.png

按多个通道计算颜色直方图
关于直方图均衡详情 请点击

# 把一个像素的多个通道合在一起看作一个值
hist = cv2.calcHist([img_bgr], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256])

hist.shape
# 含义:B取值在[0, 32), G取值在[0, 32), R取值在[0, 32)的像素个数
hist[0, 0, 0]
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容