RGB模型是工业界的一种颜色标准. 是通过对红(Red)、绿(Green)、蓝(Blue)3种颜色亮度的变化以及它们相互之间的叠加来得到各种各样的颜色。RGB彩色空间对应的坐标系统是如图所示的立方体
其实在绪论中就有说过彩色图像的相关知识,复习亿下。
像素:数字图像由二维的元素组成,每一个元素具有一个特定的位置(x,y)和幅值f(x,y),这些元素就称为像素,它是数字图像的基本单位。
彩色图像:用红、绿、蓝三元组的二维矩阵来表示。三元组的每个数值也是在0-255之间,0表示相应的基色在该像素中没有,而255表示相应的基色在该像素中取得最大值,所以越接近0越黑,越接近255越白。
利用python提取出RGB三通道图像:
代码如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
img = cv2.imread(' ')
plt.figure(dpi = 180)
plt.subplot(141)
plt.imshow(img)
plt.title("原图")
plt.subplot(142)
plt.imshow(img[:, :, 0])
plt.title("B")
plt.subplot(143)
plt.imshow(img[:, :, 1])
plt.title("G")
plt.subplot(144)
plt.imshow(img[:, :, 2])
plt.title("R")
plt.tight_layout()
plt.show()
实验结论:首先有个小问题,可以看出原图和真正的原图长得不一样, 这是因为我读取的方式采用的是opencv,而show采用的是matplotlib,这两者接口的模式不一致。opencv 的接口使用BGR模式,而 matplotlib.pyplot 接口使用的是RGB模式。所以上述原图长得不像原图。解决方法,从opencv读取后转成RGB格式 img = img[:, :, [2, 1, 0]]即可,如下所示
只需要在上述代码中读取img之后,加入 img = img[:, :, [2, 1, 0]]即可。
CMY是青(Cyan)、洋红或品红(Magenta)和黄(Yellow)三种颜色的简写,是相减混色模式,用这种方法产生的颜色之所以称为相减色,乃是因为它减少了为视觉系统识别颜色所需要的反射光。和RGB的区别在于:RGB是红(Red)、绿(Green)和蓝(Blue)三种颜色的简写,是相加混色模式,每种颜色分量越多,得到的颜色越亮,每种颜色的取值范围为0~255;RGB常用于计算机显示方面。
由于彩色墨水和颜料的化学特性,用三种基本色得到的黑色不是纯黑色,因此在印刷术中,常常加一种真正的黑色(black ink),这种模型称为CMYK模型,广泛应用于印刷术。每种颜色分量的取值范围为0~100;CMY常用于纸张彩色打印方面。
CMY和RGB其实是互补的颜色类型。
[ C M Y ] = [ 1 1 1 ] − [ R G B ] \left[\begin{array}{c} C \\ M \\ Y \end{array}\right]=\left[\begin{array}{l} 1 \\ 1 \\ 1 \end{array}\right]-\left[\begin{array}{l} R \\ G \\ B \end{array}\right] ⎣⎡CMY⎦⎤=⎣⎡111⎦⎤−⎣⎡RGB⎦⎤
以上假设所有的颜色全部归一化到了[0,1]之间,C M Y 主要表示颜料的表面所反射的颜色,上式表明涂有青色颜料的表面所反射的光中不包含红色,类似的,纯深红色不反射绿色,纯黄色不反射蓝色。所以CMY其实就是RGB的补色。
因为CMY所组合的颜色不是纯黑,所以为了产生真正的黑色,我们一般在模型里面加入CMYK的k即代表黑色。
色调H(Hue):与光波的波长有关,它表示人的感官对不同颜色的感受,如红色、绿色、蓝色等,它也可表示一定范围的颜色,如暖色、冷色等。
饱和度S(Saturation):表示颜色的纯度,纯光谱色是完全饱和的,加入白光会稀释饱和度。饱和度越大,颜色看起来就会越鲜艳,反之亦然。
亮度I(Intensity):对应成像亮度和图像灰度,是颜色的明亮程度。
HSI是指一个数字图像的模型,它反映了人的视觉系统感知彩色的方式,以色调、饱和度和亮度三种基本特征量来感知颜色。HSI模型的建立基于两个重要的事实:
第一个,分量与图像的彩色信息无关;
第二个,H和S分量与人感受颜色的方式是紧密相联的。这些特点使得HSI模型非常适合彩色特性检测与分析。
代码如下:
def RGB2HSI(rgb_img):
"""
传入RGB乳香,返回HSI图像
"""
#保存原始图像的行列数
row = np.shape(rgb_img)[0]
col = np.shape(rgb_img)[1]
#对原始图像进行复制
hsi_img = rgb_img.copy()
#对图像进行通道拆分
B,G,R = cv2.split(rgb_img)
#把通道归一化到[0,1]
[B,G,R] = [ i/ 255.0 for i in ([B,G,R])]
H = np.zeros((row, col)) #定义H通道
I = (R + G + B) / 3.0 #计算I通道
S = np.zeros((row,col)) #定义S通道
for i in range(row):
den = np.sqrt((R[i]-G[i])**2+(R[i]-B[i])*(G[i]-B[i]))
thetha = np.arccos(0.5*(R[i]-B[i]+R[i]-G[i])/den) #计算夹角
h = np.zeros(col) #定义临时数组
#den>0且G>=B的元素h赋值为thetha
h[B[i]<=G[i]] = thetha[B[i]<=G[i]]
#den>0且G<=B的元素h赋值为thetha
h[G[i]<B[i]] = 2*np.pi-thetha[G[i]<B[i]]
#den<0的元素h赋值为0
h[den == 0] = 0
H[i] = h/(2*np.pi) #弧度化后赋值给H通道
#计算S通道
for i in range(row):
min = []
#找出每组RGB值的最小值
for j in range(col):
arr = [B[i][j],G[i][j],R[i][j]]
min.append(np.min(arr))
min = np.array(min)
#计算S通道
S[i] = 1 - min*3/(R[i]+B[i]+G[i])
#I为0的值直接赋值0
S[i][R[i]+B[i]+G[i] == 0] = 0
#扩充到255以方便显示,一般H分量在[0,2pi]之间,S和I在[0,1]之间
hsi_img[:,:,0] = H*255
hsi_img[:,:,1] = S*255
hsi_img[:,:,2] = I*255
return hsi_img
伪彩色图像处理也叫假彩色图像处理,根据一定的准则对灰度值赋以彩色的处理。
灰度级分层通常用于突出感兴趣的特定灰度范围内的亮度。灰度级分层有两大基本方法。
代码如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
def grayscale_layer(input_image, spotlight_range_min, spotlight_range_max, means):
'''
灰度级分层
:param input_image: 原图像
:param spotlight_range_min: 所突出的灰度级范围最小值
:param spotlight_range_max: 所突出的灰度级范围最大值
:param means: 分层方式(1,2)
:return: 灰度级分层后的图像
'''
input_image_cp = np.copy(input_image) # 输入图像的副本
if means == 1: # 方式一(突出指定范围内255,并且变暗非范围内0)
input_image_cp = np.where((input_image_cp >= spotlight_range_min) & (input_image_cp <= spotlight_range_max), 255, 0)
elif means == 2: # 方式二(仅突出指定范围内255)
input_image_cp[np.where((input_image_cp >= spotlight_range_min) & (input_image_cp <= spotlight_range_max))] = 255
else:
print("please enter the number of means from 1 to 2")
return
output_image = input_image_cp
return output_image.astypetype(np.uint8)
img = cv2.imread(' ')
img = img[:, :, [2, 1, 0]]
plt.figure(dpi = 180)
plt.subplot(131)
plt.imshow(img)
plt.title("原图")
plt.subplot(132)
plt.imshow(output_1)
plt.title("output_1")
plt.subplot(133)
plt.imshow(output_2)
plt.title("output_2")
plt.tight_layout()
plt.show()
首先我们需要一张灰度图,读取灰度图的方式有好几种,这里用opencv读取灰度图,然后用matplotlib显示。读取方式为:
img = cv2.imread(' ', 0) # 0代表着以灰度图的方式读取
但是直接使用plt显示图像,它默认使用三通道显示图像。所以你管这绿的叫灰度图?所以在plt.imshow()添加参数,plt.imshow(img, cmap=“gray”),这样就能得到正经的灰度图。
opencv中自带函数cv2.applyColorMap(img, cv2.COLORMAP_JET)能将灰度图像转化成伪彩色图像,效果如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
img = cv2.imread('C:/Users/yujunliu/Pictures/Saved Pictures/dongman.jpg', 0)
img = img[:, :, [2, 1, 0]]
im_color = cv2.applyColorMap(img, cv2.COLORMAP_JET)
plt.figure(dpi = 100)
plt.subplot(121)
plt.imshow(img, cmap = "gray")
plt.title("灰度图")
plt.subplot(122)
plt.imshow(im_color)
plt.title("伪彩色图像")
plt.tight_layout()
plt.show()
彩色空间分割是基于单色图像(灰度图)分割技术在不同颜色通道上实现的。灰度图分割技术常见的有:直方图阀值化、特征聚类、边缘检测、基于区域的、模糊技术、神经网络等。灰度图的分割方法都是基于区域像素的非连续性或相似性。基于非连续性的方法主要是为了检测孤立的点、边缘、线(灰度突然变化的地方)。基于相似性的方法包括阀值、聚类、区域分割合并等。
本次目标是将一副图像从rgb颜色空间转换到hsv颜色空间,颜色去除白色背景部分具体就调用了cv2的两个函数,一个是rgb转hsv的函数,另一个是利用cv2.inRange函数设阈值,去除背景部分。
代码如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
def color_seperate(image):
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) #对目标图像进行色彩空间转换
#设定蓝色下限
lower_hsv = np.array([20, 20, 20])
#设定蓝色上限
upper_hsv = np.array([255, 255, 255])
mask = cv2.inRange(hsv, lowerb=lower_hsv, upperb=upper_hsv)
dst = cv2.bitwise_and(image, image, mask=mask)
return dst
img = cv2.imread(' ')
out = color_seperate(img)
plt.figure(dpi = 100)
plt.subplot(121)
plt.imshow(img)
plt.title("原图")
plt.subplot(122)
plt.imshow(out)
plt.title("output")
plt.tight_layout()
plt.show()
核心函数在于cv2.inRange,参数有三个
第一个参数:原图
第二个参数:lower_red指的是图像中低于这个lower_red的值,图像值变为0
第三个参数:upper_red指的是图像中高于这个upper_red的值,图像值变为0
而在lower_red~upper_red之间的值变成255
在图像识别中,需要有边缘鲜明的图像,即图像锐化。图像锐化的目的是为了突出图像的边缘信息,加强图像的轮廓特征,以便于人眼的观察和机器识别。图像边缘检测大幅度地减少了数据量,并且剔除了可以认为不相关的信息,保留了图像重要的结构属性。本次利用Canny算子来实现边缘检测。图像边缘检测必须满足两个条件,一能有效地抑制噪声;二必须尽量精确确定边缘的位置。根据对信噪比与定位乘积进行测度,得到最优化逼近算子,这就是Canny边缘检测算子。
Canny 的目标是找到一个最优的边缘检测算法,最优边缘检测的含义是:
最好的检测: 算法能够尽可能多地标识出图像中的实际边缘。
最好的定位: 标识出的边缘要尽可能与实际图像中的实际边缘尽可能接近。
最小的响应:图像中的边缘只能标识一次,并且可能存在的图像噪声不应标识为边缘。
这里采用opencv C++版本调用摄像头实现Candy算子:
代码如下:
#include
#include
using namespace cv;
int main()
{
VideoCapture capture(0);
while (1)
{
Mat frame;
Mat dstImage, edge, grayImage; //参数定义
capture >> frame;
//将原图像转换为灰度图像
cvtColor(frame, grayImage, CV_BGR2GRAY);
//先用使用 3x3内核来降噪
blur(grayImage, edge, Size(3, 3));
//运行Canny算子
Canny(edge, edge, 3, 9, 3);
imshow("读取视频", edge);
waitKey(30);
}
return 0;
}