这次作业需要记录的有三道题,包括:
- 拜尔图像
- 目标转换
- 图片过滤和边缘检测
(1)Bayer Interpolation
作业要求:
简单来说,即是给出一张Bayer图片,将其转化为RGB图。
作业给出的图片如下:
这里先对Bayer图进行简要说明。
与一般RGB图不同,Bayer图的像素分布如下图所示:
由此可以发现,在Bayer图中,每个像素点都是由单一颜色所控制,而且绿色所占的比例是其他两种颜色的两倍,所以整张图片看起来会偏绿,我们所要做的就是通过插值将每个像素点的其他两种颜色算出来。
步骤1:
将Bayer数据分成RGB通道,以便每个颜色通道仅保留Bayer模式给定的相应值,而缺失值则用零填充。
def separatechannels(bayerdata):
""" Separate bayer data into RGB channels so that
each color channel retains only the respective
values given by the bayer pattern and missing values
are filled with zero
Args:
Numpy array containing bayer data (H,W)
Returns:
red, green, and blue channel as numpy array (H,W)
"""
H, W = bayerdata.shape
r = np.zeros((H, W))
g = np.zeros((H, W))
b = np.zeros((H, W))
for i in range(H):
for j in range(W):
if((i + j) % 2 == 0):
g[i][j] = bayerdata[i][j]
elif(i % 2 == 0 and (i + j) % 2 != 0):
r[i][j] = bayerdata[i][j]
elif(i % 2 != 0 and (i + j) % 2 != 0):
b[i][j] = bayerdata[i][j]
return r, g, b
步骤2:
将单独的通道组合成图像。
def assembleimage(r, g, b):
""" Assemble separate channels into image
Args:
red, green, blue color channels as numpy array (H,W)
Returns:
Image as numpy array (H,W,3)
"""
H, W = r.shape
imgData = np.zeros((H, W, 3))
imgData[:,:,0] = r[:,:]
imgData[:,:,1] = g[:,:]
imgData[:,:,2] = b[:,:]
return imgData
结果如下图:
步骤3:
通过使用双线性插值对Bayer模式中的缺失值进行插值。
双线性插值,简单来说就是通过邻近4个点平均出中间点的数值。
其实主要就是计算R,G,B三通道的卷积核。说之前先解释一个函数:scipy.ndimage.filters.convolve,(python的各种库里有非常多用于卷积的函数,改天做个对比总结)。
scipy.ndimage.filters.convolve:
(这里给个 链接,说得很详细了已经)
scipy.ndimage.filters.convolve(input, weights, output=None,
mode=‘reflect’, cval=0.0, origin=0)
input: 待卷积的图片
weight: 卷积核
output:(这个未知,好像一直没用过这个,(待定))
mode: 边缘处理,有5种(关于各个边缘模式的选用现在还未理解)
‘reflect’ (d c b a | a b c d | d c b a)
‘constant’ (k k k k | a b c d | k k k k)
‘nearest’ (a a a a | a b c d | d d d d)
‘mirror’ (d c b | a b c d | c b a)
‘wrap’ (a b c d | a b c d | a b c d)
cval:默认是0,当mode取constant时有效,这个的取值既是边缘外补什么值
origin:默认0,应该是控制weight在input上的位置的,目前也还没用过
这里有一个要特别注意的是,卷积核不是直接对应相乘然后相加,而是要先翻转,举个例子,比如一个卷积核设为:
但实际上并不是上面这个与图片卷积,而是下面这个卷积核:
这点在初始化卷积核的时候要注意(不过目前遇到的好像都是中心对称的)
回到题里,G通道对应的矩阵如下图:
按照双线性插值,很容易能得到卷积核四个角的值,又由于应该把原本的像素值保留下来,再根据边界插值条件,就可以确定出通道G的卷积核,其他两个通道同理可各自获得卷积核值。
代码如下:
def interpolate(r, g, b):
""" Interpolate missing values in the bayer pattern
by using bilinear interpolation
Args:
red, green, blue color channels as numpy array (H,W)
Returns:
Interpolated image as numpy array (H,W,3)
"""
r_weight = np.array([[0.25,0.5,0.25],[0.5,1,0.5],[0.25,0.5,0.25]])
g_weight = np.array([[0,0.25,0],[0.25,1,0.25],[0,0.25,0]])
b_weight = np.array([[0.25,0.5,0.25],[0.5,1,0.5],[0.25,0.5,0.25]])
new_r = convolve(r, r_weight, mode='mirror')
new_g = convolve(g, g_weight, mode='mirror')
new_b = convolve(b, b_weight, mode='mirror')
#print(new_g)
#print(new_r)
#print(new_b)
H, W = new_r.shape
new_img = np.zeros((H, W, 3))
new_img[:,:,0] = new_r[:,:]
new_img[:,:,1] = new_g[:,:]
new_img[:,:,2] = new_b[:,:]
return new_img
最后得到的图片如下:
总结:
本次作业及该篇学习记录遗留下的问题:
- 卷积的mode是“mirror”,原因未明;
- 要对python里各个库的卷积函数进行总结;
- 这次作业用到的卷积函数的output以及origin参数