渐变掩模
对于规则形状,比如圆形的渐变掩模生成是比较简单的,因为每一圈上像素的位置是固定的,只需要对每一圈上的像素填充上不同的值即可生成渐变的Mask,如图1所示为一个圆形的渐变Mask。 图1
但是这种Mask生成方式并不适用于不规则的形状,下面将描述一种生成不规则形状Mask的方法。
不规则渐变Mask的生成
如图2所示为一个不规则的圆环形状。如果希望图示的白色区域是一个渐变的显示,则可以图像中心为原点,作多条直线进行采样(图3),则可得到每条直线穿过的像素点坐标,继而实现径向的像素值的渐变。 图2 本示例的采样率为1degree,即每旋转1°采样一次,图3仅展示部分角度的采样直线。 图3
最终的渐变Mask如图4所示,沿着不规则环形的内侧边缘,每个径向有10步(10个像素)下降。
代码实现
定义
import os
import numpy as np
import math
from matplotlib import pyplot as plt
from scipy.interpolate import interp1d
import cv2
sample_freq = 1
sample_steps = int(180/sample_freq)
coordinate_xAxis = np.reshape(np.arange(0,128),(1,128))
coordinate_xAxis = np.repeat(coordinate_xAxis,128,axis=0)
coordinate_xAxis = coordinate_xAxis-64+0.5
coordinate_yAxis = np.reshape(np.arange(127,-1,-1),(128,1))
coordinate_yAxis = np.repeat(coordinate_yAxis,128,axis=1)
coordinate_yAxis = coordinate_yAxis-64+0.5
angle = np.arctan(coordinate_yAxis/coordinate_xAxis)*180/math.pi
angle[angle<0] +=180
pixel_index = []
line_index_1 = np.floor(angle/sample_freq)
line_index_2 = np.ceil(angle/sample_freq)
计算采样直线通过的像素坐标
for i in range(sample_steps):
flag1 = np.argwhere(line_index_1==i)
flag2 = np.argwhere(line_index_2==i)
flag = np.concatenate((flag1,flag2),axis=0)
z = np.ones((128,128))
z[flag[:,0],flag[:,1]] = 100
if i*sample_freq<=45 or i*sample_freq>=135:
for col in range(128):
try:
if col<64:
preserve_pixel_idx = np.argwhere(z[:,col]==100)[-1]
else:
preserve_pixel_idx = np.argwhere(z[:,col]==100)[0]
except:
continue
z[preserve_pixel_idx[0],col] = 500
if i*sample_freq>45 and i*sample_freq<135:
for row in range(128):
try:
if row<64:
preserve_pixel_idx = np.argwhere(z[row,:]==100)[-1]
else:
preserve_pixel_idx = np.argwhere(z[row,:]==100)[0]
except:
continue
z[row,preserve_pixel_idx[0]] = 500
flag_z = np.argwhere(z==500)
zz = np.ones((128,128))
zz[flag_z[:,0],flag_z[:,1]] = 500
if i*sample_freq>45 and i*sample_freq<135:
col_value = np.unique(flag_z[:,1])
cnt=0
for r in col_value:
temp = np.argwhere(flag_z[:,1]==r)
if cnt==0:
flag_final = np.squeeze(flag_z[temp],axis=1)
else:
flag_final = np.concatenate((flag_final,np.squeeze(flag_z[temp],axis=1)),axis=0)
cnt = cnt+1
f = interp1d(flag_final[:,0],flag_final[:,1])
y = np.expand_dims(f(np.arange(flag_final[:,0].min(),flag_final[:,0].max()+1)),axis=1)
y = np.round(y)
x = np.expand_dims(np.arange(flag_final[:,0].min(),flag_final[:,0].max()+1),axis=1)
flag_final_ = np.concatenate((y,x),axis=1)
zzz = np.ones((128,128))
zzz[flag_final_[:,1].astype('int'),flag_final_[:,0].astype('int')] = 500
if i*sample_freq<=45 or i*sample_freq>=135:
row_value = np.unique(flag_z[:,0])
cnt=0
for r in row_value:
temp = np.argwhere(flag_z[:,0]==r)
if cnt==0:
flag_final = np.squeeze(flag_z[temp][::-1],axis=1)
else:
flag_final = np.concatenate((flag_final,np.squeeze(flag_z[temp][::-1],axis=1)),axis=0)
cnt = cnt+1
f = interp1d(flag_final[:,1],flag_final[:,0])
y = np.expand_dims(f(np.arange(flag_final[:,1].min(),flag_final[:,1].max()+1)),axis=1)
y = np.round(y)
x = np.expand_dims(np.arange(flag_final[:,1].min(),flag_final[:,1].max()+1),axis=1)
flag_final_ = np.concatenate((y,x),axis=1)
zzz = np.ones((128,128))
zzz[flag_final_[:,0].astype('int'),flag_final_[:,1].astype('int')] = 500
plt.imshow(zzz)
pixel_index.append(flag_final_.astype('int'))
给径向像素赋值生成渐变图像
for root, dirs, files in os.walk(root_path):
for name in files:
ct = np.load('your image')
sample_weight = np.ones((128,128))
for i in range(sample_steps):
value_line = []
if i*sample_freq<=45 or i*sample_freq>=135:
for m in pixel_index[i]:
value_line.append(ct[m[0],m[1]])
if i*sample_freq>45 and i*sample_freq<135:
for m in pixel_index[i]:
value_line.append(ct[m[1],m[0]])
value_line = np.array(value_line)
zeros_index_on_line = np.squeeze(np.argwhere(value_line==0))
border_on_line = np.argwhere(np.diff(zeros_index_on_line)!=1)
border_on_line[0] = border_on_line[0]+1
border_on_img = np.squeeze(pixel_index[i][zeros_index_on_line[border_on_line]])
if border_on_img.size!=4:
continue
border = np.ones((128,128))
if i*sample_freq<=45 or i*sample_freq>=135:
border[border_on_img[:,0],border_on_img[:,1]] = 500
if i*sample_freq>45 and i*sample_freq<135:
border[border_on_img[:,1],border_on_img[:,0]] = 500
border_around_on_img = []
border_around_on_line = border_on_line.copy()
for v in range(10):
border_around_on_line[0] = zeros_index_on_line[border_on_line][0]-(v+1)
border_around_on_line[1] = zeros_index_on_line[border_on_line][1]+(v+1)
tmp = np.squeeze(pixel_index[i][border_around_on_line])
border_around_on_img.append(tmp)
if i*sample_freq<=45 or i*sample_freq>=135:
sample_weight[tmp[:,0],tmp[:,1]] = (10-v)*5
if i*sample_freq>45 and i*sample_freq<135:
sample_weight[tmp[:,1],tmp[:,0]] = (10-v)*5
讨论
这种不规则形状的渐变掩模应该也可以通过腐蚀膨胀操作来实现,但是腐蚀膨胀操作的系数不好控制,无法精确到单个像素。
|