文章目錄
- 基本概念
-
- RGB空間
- HSV空間
- HSL空間
- 色彩變換
-
- 灰階變換
- 色彩反向、調整像素區間
- 增強對比度
-
- 直方圖均衡化
- 圖像平滑/減少噪聲
-
- 圖像平均
- 高斯濾波
- 圖像梯度
-
- sobel算子/scharr算子
- prewitt算子
- Laplacian 算子
- 參考及更多閱讀
基本概念
RGB空間
RGB 是最基本、最常用、最接近硬體的色彩空間表示。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiIXZ05WZj91YpB3I0IjYwBHWhlXOHFWNCh0YohmMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzITNyMDNyUTM1ETOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
但是真實世界中還有光照、遮擋、陰影等多種情況,而且人眼對RGB三種顔色分量的敏感度也是不一樣的,如果色彩的相似性直接用歐式距離來度量,結果會與視覺直覺有很大差距。
是以,RGB适合與顯示系統,但是不适合圖像處理。
openCV提取不同通道的顔色
import cv2 as cv
src=cv.imread('rgb.jpg')
cv.namedWindow('first_image', cv.WINDOW_AUTOSIZE)
cv.imshow('first_image', src)
#三通道分離形成單通道圖檔
b, g, r =cv.split(src)
cv.imshow("second_blue", b)
cv.imshow("second_green", g)
cv.imshow("second_red", r)
HSV空間
- H:Hue,色調,色相
- S:Saturation,飽和度,色彩純淨度
- V:value,明度
HSV更接近人眼的直覺感受。具體來說:
H參數表示色彩資訊,即所處的光譜顔色的位置。該參數用角度量來表示,紅、綠、藍分别相隔120度。互補色分别相差180度。
純度S為一比例值,範圍從0到1,它表示成所選顔色的純度和該顔色最大的純度之間的比率。S=0時,隻有灰階。
V表示色彩的明亮程度,範圍從0到1。有一點要注意:它和光強度之間并沒有直接的聯系。
怎麼了解HSV呢?
這裡引入極坐标系,紅藍綠三個顔色分别位于0度,120度和240度,在色彩極坐标系中,“純度”與目前色彩的角度位置有關,越接近紅-綠-藍對應的角度,是以,純度也稱為色相,顧名思義,就是用目前色彩與三原色之間的相位關系來描述。
在極坐标系中,矢量除了相位以外,還有“模”的關系,原點是“灰色”,模值越大,色彩就越鮮豔,最大值是255。這裡的“模”值就是飽和度。
但是如何形容顔色的亮度呢?我們引入三維直角坐标系,三個坐标軸分别表示RGB的取值。很顯然,原點(0,0,0)是黑色,(255,255,255 )是白色,(255,0,0)紅色,(0,255,0)綠色,(0,0,255)藍色。
如果從原點出發,到(255,255,255)白色連一條對角線,這條對角線就是“明度”軸了。越接近原點就越“暗”, 越接近白色的對角點就越“亮”。
如果回到之前的極坐标系,亮度應該如何表示呢?顯然,我們需要引入一個縱軸表示明暗關系。
但是上面的圖并不是特别“科學”,因為最“暗”的原點處,應該是一個點,整個色彩空間應該是一個圓錐的形狀。
- openCV 中HSV色彩空間的轉換
跑一下openCV 幫助文檔中的經典例子,随手拿起手邊的藍色電腦内膽包被成功捕獲了。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Sep 15 15:05:19 2019
"""
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while(1):
# Take each frame
_, frame = cap.read()
# Convert BGR to HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# define range of blue color in HSV
lower_blue = np.array([100,50,50])
upper_blue = np.array([140,255,255])
# Threshold the HSV image to get only blue colors
mask = cv2.inRange(hsv, lower_blue, upper_blue)
# Bitwise-AND mask and original image
res = cv2.bitwise_and(frame,frame, mask= mask)
cv2.imshow('frame',frame)
cv2.imshow('mask',mask)
cv2.imshow('res',res)
k = cv2.waitKey(5) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
注意其中這一句:
這一句是将攝像頭捕獲的色彩從RGB空間轉換到HSV空間,随後的代碼用HSV方式指定特定的色彩範圍。第一個值是H,就是色相,在openCV的HSV定義中,藍色是在120度,這裡指定100-140之間,S和V的取值在50-255之間。
更多色彩轉換,見幫助文檔: https://docs.opencv.org/3.1.0/de/d25/imgproc_color_conversions.html
HSL空間
HSL與HSV的定義很類似,H也是色相,S也是飽和度,L則代表brightness,是亮度。亮度越高,越接近白色,越低,越接近黑色。而HSV中的最後一個值明度,越小越接近黑色,越大,色彩越鮮明。可見,HSL的定義更符合人眼的視覺感受。
H:
S:
L:
色彩變換
灰階變換
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
im0 = Image.open('car.jpg')
im_grey = im0.convert('L') # 灰階變換
im_grey.show()
色彩反向、調整像素區間
im = np.array(im_grey)
im2 = 255-im # 對圖像進行反向處理
im3 = (100/255)*im+100 #将圖像的像素變換到100-200之間
im4 = 255*(im/255)**2 # 對圖像像素值平方後得到的圖像
plt.subplots()
plt.subplot(131), plt.imshow(im2)
plt.subplot(132), plt.imshow(im3)
plt.subplot(133), plt.imshow(im4)
增強對比度
對比度指的是一幅圖像中明暗區域最亮的白和最暗的黑之間不同亮度層級的測量,差異範圍越大代表對比度越大,差異範圍越小代表對比度越小。
對比度增強技術主要解決圖像灰階級範圍較小造成的對比度低問題,目的是将圖像的灰階級放大到指定的程度,使圖像中的細節看起來更加清晰。
直方圖均衡化
直方圖均衡化是将一副圖像的灰階直方圖變平,使得變換後圖像中的每個灰階值的分布機率相同。該方法通常用于是灰階值進行歸一化,可以增強圖像的對比度。
# 直方圖均衡化
import numpy as np
def histeq(im, nbr_bins=256):
# 計算圖像的直方圖
imhist, bins = np.histogram(im.flatten(), nbr_bins, normed=True)
cdf = imhist.cumsum() # 累計分布函數
cdf = 255*cdf/cdf[-1] # 歸一化
im2 = np.interp(im.flatten(), bins[:-1], cdf)
return im2.reshape(im.shape), cdf
from PIL import Image
import matplotlib.pyplot as plt
im0 = Image.open('car.jpg')
im_grey = np.array(im0.convert('L')) # 灰階變換, 并轉化為numpy array
im2,cdf = histeq(im_grey)
plt.subplots()
plt.subplot(121), plt.imshow(im_grey)
plt.subplot(122), plt.imshow(im2)
圖像平滑/減少噪聲
圖像平均
圖像平均是一種減少圖像噪聲的簡單方式,通常用于藝術特效。簡單滴說就是将所有圖像求和做平均。
高斯濾波
将圖像與高斯核做卷積得到
I σ = I ∗ G σ I_\sigma = I * G_\sigma Iσ=I∗Gσ
其中I代表一個圖像,G表示标準差為 δ \delta δ 的二維高斯核
G σ = 1 2 π σ 2 e − ( x 2 + y 2 ) / 2 σ 2 G_\sigma = \frac{1}{2\pi\sigma^2}e^{-(x^2+y^2)/2\sigma^2} Gσ=2πσ21e−(x2+y2)/2σ2
from PIL import Image
from numpy import *
from scipy.ndimage import filters
# 對灰階圖模糊
im = array(Image.open('car.jpg').convert('L'))
im2 = filters.gaussian_filters(im,5)
# 對彩色圖模糊, 要求每個通道進行操作
im = array(Image.open('car.jpg'))
im2 = zeros(im.shape)
for i in range(3):
im2[:,:,i] = filters.gaussian_filter(im[:,:,i],5)
im2 = unit8(im2)
openCV也提供了很多濾波工具,例如:
blur: 對各種噪聲都有一定的抑制作用
GaussianBlur: 對随機噪聲比較好,對椒鹽噪聲效果不好
medianBlur: 對椒鹽噪聲效果比較好
fastNlMeansDenoising: 非局部去噪,速度很慢,可以調參的去噪方法, 隻支援輸入是灰階圖像的
fastNlMeansDenoisingColored: 同上,去噪針對彩色圖像
椒鹽噪聲就是非常零散的,近似呈均勻分布的散點狀白色/黑色噪聲,如下圖。對椒鹽噪聲中值濾波效果比較好,對高斯噪聲非局部均值去噪效果比較好.
圖像梯度
圖像的梯度向量包括兩層含義,一個是梯度的大小, 描述了圖像強度變化的大小,另一個是梯度的方向,描述了圖像強度變化的方向。
sobel算子/scharr算子
Sobel 算子是高斯平滑與微分操作的結合體,是以它的抗噪聲能力很好,可以設定求導的方向(xorder 或 yorder),還可以設定使用的卷積核的大小(ksize),如果 ksize=-1,會使用 3x3 的 Scharr 濾波器,它的的效果要比 3x3 的 Sobel 濾波器好(而且速度相同,是以在使用 3x3 濾波器時應該盡量使用 Scharr 濾波器)。 3x3 的 Scharr 濾波器卷積核如下
prewitt算子
Prewitt算子是一種一階微分算子的邊緣檢測,利用像素點上下、左右鄰點的灰階差,在邊緣處達到極值檢測邊緣,去掉部分僞邊緣,對噪聲具有平滑作用 。其原理是在圖像空間利用兩個方向模闆與圖像進行鄰域卷積來完成的,這兩個方向模闆一個檢測水準邊緣,一個檢測垂直邊緣。
Laplacian 算子
拉普拉斯算子可以使用二階導數的形式定義,可假設其離散實作類似于二階 Sobel 導數,事實上, OpenCV 在計算拉普拉斯算子時直接調用 Sobel 算子。
scipy和opencv都提供了相應工具,例如:
from PIL import Image
from numpy import *
from scipy.ndimage import filters
im = array(Image.open('car.jpg').convert('L'))
# sobel filter
imx = zeros(im.shape)
filters.sobel(im,1,imx)
imy = zeros(im.shape)
filters.sobel(im, 0, imy)
matnitude = sqrt(imx**2+imy**2)
import matplotlib.pyplot as plt
plt.subplots()
plt.subplot(121), plt.imshow(imx)
plt.subplot(122), plt.imshow(imy)
prewitt濾波器, 也可以調用scipy.ndimage的filters子產品得到。
opencv中,直接調用Sobel函數或者Laplacian函數就可以, 例如:
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('me.jpg',0)
laplacian = cv2.Laplacian(img, cv2.CV_64F)
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0,ksize=5)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1,ksize=5)
plt.subplot(2,2,1),plt.imshow(img,cmap='gray')
plt.title('Original'),plt.xticks([]),plt.yticks([])
plt.subplot(2,2,2),plt.imshow(laplacian,cmap='gray')
plt.title('Laplacian'),plt.xticks([]),plt.yticks([])
plt.subplot(2,2,3),plt.imshow(sobelx,cmap='gray')
plt.title('Sobel_X'),plt.xticks([]),plt.yticks([])
plt.subplot(2,2,4),plt.imshow(sobely,cmap='gray')
plt.title('Sobel_Y'),plt.xticks([]),plt.yticks([])
plt.show()
參考及更多閱讀
OpenCV圖像噪聲與去噪函數方法對比使用介紹:
https://cloud.tencent.com/developer/article/1165771
opencv圖像梯度:
https://blog.csdn.net/u010682375/article/details/70140803
opencv 彩色圖像對比度增強: