Opencv颜空间转换、直方图、Gamma变换

Opencv颜⾊空间转换、直⽅图、Gamma变换
⼀、颜⾊空间转换
cv2.cvtcolor(img,code)
code——转换的标识,从什么空间转换到什么空间,常⽤的有:cv2.COLOR_BGR2HSV、cv2.COLOR_HSV2BGR、
cv2.COLOR_GRAY2BGR、cv2.COLOR_BGR2GRAY
HSV空间:HSV空间是由美国的图形学专家A. R. Smith提出的⼀种颜⾊空间,HSV分别是⾊调(Hue),饱和度(Saturation)和明度(Value)。在HSV空间中进⾏调节就避免了直接在RGB空间中调节是还需要考虑三个通道的相关性。OpenCV中H的取值是[0, 180),其他两个通道的取值都是[0, 256),⽤于调节⾊调和明暗。
⽰例:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('scene.jpg')
# 通过cv2.cvtColor把图像从BGR转换到HSV
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# H空间中,通过增加像素灰度值可以改变图像的⾊调
turn_green_hsv = py()
turn_green_hsv[:, :, 0] = (turn_green_hsv[:, :, 0]+150) % 180
turn_green_img = cv2.cvtColor(turn_green_hsv, cv2.COLOR_HSV2BGR)
cv2.imwrite('turn_green.jpg', turn_green_img)
# 减⼩饱和度会让图像损失鲜艳,变得更灰
colorless_hsv = py()
colorless_hsv[:, :, 1] = 0.5 * colorless_hsv[:, :, 1]
colorless_img = cv2.cvtColor(colorless_hsv, cv2.COLOR_HSV2BGR)
cv2.imwrite('colorless.jpg', colorless_img)
# 减⼩明度为原来⼀半
darker_hsv = py()
darker_hsv[:, :, 2] = 0.5 * darker_hsv[:, :, 2]
darker_img = cv2.cvtColor(darker_hsv, cv2.COLOR_HSV2BGR)
cv2.imwrite('darker.jpg', darker_img)
⾊调饱和度明暗
⼆、直⽅图
⽆论是HSV还是RGB,我们都较难⼀眼就对像素中值的分布有细致的了解,这时候就需要直⽅图,Opencv中直⽅图计算函数为:
cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]]) #返回hist
各参数:
channels:直⽅图计算的通道[0]、[1]、[2]
mask:可选的操作掩码。如果此掩码不为空,那么它必须为8位并且尺⼨要和输⼊图像images[i]⼀致
histSize:表⽰这个直⽅图分成多少份(即多少个直⽅柱)
ranges:直⽅图中各个像素的值,[0,256]表⽰直⽅图能表⽰从0到256像素值的像素accumulate:布尔量,表⽰直⽅图是否可以叠加
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__':
img = cv2.imread("scene.jpg")
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()
其中函数minMaxLoc()在C++下表⽰为:
void cv::minMaxLoc  (  InputArray      src,
double *    minVal,
double *    maxVal = 0,
Point *    minLoc = 0,
Point *    maxLoc = 0,
InputArray      mask = noArray()
)
参数解释
src: 输⼊的单通道数组
minVal: double类型指针,⽤于返回最⼩值的指针,如果不需要返回则设置为NULL
maxVal: double类型的指针,⽤于返回最⼤值指针,如果不需要返回则设置为NULL
minLoc: 返回最⼩值位置指针(2D的情况下),如果不需要则设置为NULL
maxLoc: 返回最⼤位置指针(2D情况下),如果不需要则设置为NULL
mask: 可选掩模板。
表⽰成折线图:
import cv2
import numpy as np
img = cv2.imread('scene.jpg')
h = np.zeros((256,256,3)) #创建⽤于绘制直⽅图的全0图像
bins = np.arange(256).reshape(256,1) #直⽅图中各bin的顶点位置
color = [ (255,0,0),(0,255,0),(0,0,255) ] #BGR三种颜⾊
for ch, col in enumerate(color):
originHist = cv2.calcHist([img],[ch],None,[256],[0,256])
hist=np.int32(np.around(originHist))
pts = np.column_stack((bins,hist))
cv2.polylines(h,[pts],False,col)
h=np.flipud(h)
cv2.imshow('colorhist',h)
cv2.waitKey(0)
主要⽤到的函数包括alize()、np.column_stack(),、含义如下:
void cv::normalize  (  InputArray      src,
InputOutputArray    dst,
double      alpha = 1,
double      beta = 0,
int    norm_type = NORM_L2,
int    dtype = -1,
InputArray      mask = noArray()
)
参数解释
src: 输⼊数组
dst: 输出数组,与src有相同的尺⼨
alpha: 将数组归⼀化范围的最⼤值,有默认值1
beta: 归⼀化的最⼩值,有默认值0
norm_type: 归⼀化⽅式,可以查看NormTypes()函数查看详细信息,有默认值NORM_L2
dtype: 当该值取负数时,输出数组与src有相同类型,否则,与src有相同的通道并且深度为CV_MAT_DEPTH(dtype)
mask: 可选的掩膜版
三、Gamma变换
背景⾥的暗部细节是⾮常弱的时候,⼀个常⽤⽅法是考虑⽤Gamma变换来提升暗部细节。Gamma变换是矫正相机直接成像和⼈眼感受图像差别的⼀种常⽤⼿段,简单来说就是通过⾮线性变换让图像从对曝光强度的线性响应变得更接近⼈眼感受到的响应。具体的定义和实现,还是接着上⾯代码中读取的图⽚,执⾏计算直⽅图和Gamma变换的代码如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
img = cv2.imread('scene.jpg')
# 分通道计算每个通道的直⽅图
hist_b = cv2.calcHist([img], [0], None, [256], [0, 256])
hist_g = cv2.calcHist([img], [1], None, [256], [0, 256])
hist_r = cv2.calcHist([img], [2], None, [256], [0, 256])
# 定义Gamma矫正的函数
def gamma_trans(img, gamma):
# 具体做法是先归⼀化到1,然后gamma作为指数值求出新的像素值再还原
gamma_table = [np.power(x/255.0, gamma)*255.0 for x in range(256)]
gamma_table = np.round(np.array(gamma_table)).astype(np.uint8)
# 实现这个映射⽤的是OpenCV的查表函数
return cv2.LUT(img, gamma_table)
# 执⾏Gamma矫正,⼩于1的值让暗部细节⼤量提升,同时亮部细节少量提升
dst指数img_corrected = gamma_trans(img, 0.5)
cv2.imwrite('gamma_corrected.jpg', img_corrected)
# 分通道计算Gamma矫正后的直⽅图
hist_b_corrected = cv2.calcHist([img_corrected], [0], None, [256], [0, 256])
hist_g_corrected = cv2.calcHist([img_corrected], [1], None, [256], [0, 256])
hist_r_corrected = cv2.calcHist([img_corrected], [2], None, [256], [0, 256])
fig = plt.figure()
pix_hists = [
[hist_b, hist_g, hist_r],
[hist_b_corrected, hist_g_corrected, hist_r_corrected]
]
pix_vals = range(256)
for sub_plt, pix_hist in zip([121, 122], pix_hists):
ax = fig.add_subplot(sub_plt, projection='3d')
for c, z, channel_hist in zip(['b', 'g', 'r'], [20, 10, 0], pix_hist):
cs = [c] * 256
#ax.bar(pix_vals, channel_hist, zs=z, zdir='y', color=cs, alpha=0.618, edgecolor='none', lw=0)
ax.plot3D(pix_vals, channel_hist, zs=z,zdir='y',color=c)
ax.set_xlabel('Pixel Values')
ax.set_xlim([0, 256])
ax.set_ylabel('Channels')
ax.set_zlabel('Counts')
plt.show()
直⽅图 原图 gamma变换之后

本文发布于:2024-09-21 20:30:52,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/3/380290.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:通道   空间   像素   图像   需要   函数   指针   细节
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议