不规则形状渐变掩模(gradient mask)的生成

渐变掩模

对于规则形状,比如圆形的渐变掩模生成是比较简单的,因为每一圈上像素的位置是固定的,只需要对每一圈上的像素填充上不同的值即可生成渐变的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 # deg
sample_steps = int(180/sample_freq)
coordinate_xAxis = np.reshape(np.arange(0,128),(1,128)) #1*128
coordinate_xAxis = np.repeat(coordinate_xAxis,128,axis=0) # 128*128
coordinate_xAxis = coordinate_xAxis-64+0.5
coordinate_yAxis = np.reshape(np.arange(127,-1,-1),(128,1)) #128*1
coordinate_yAxis = np.repeat(coordinate_yAxis,128,axis=1) # 128*128
coordinate_yAxis = coordinate_yAxis-64+0.5
angle = np.arctan(coordinate_yAxis/coordinate_xAxis)*180/math.pi # degree
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
    # plt.imshow(zz)  

    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) # 可以plot出图3的采样直线
    ## 注意! angle<=45 or angle>=135的情况,pixel_index中存储的是[row_idx,col_idx];
    ##  angle>45 and angle<135的情况,pixel_index中存储的是[col_idx,row_idx]
    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)  # two points
            border_on_line[0] = border_on_line[0]+1

            border_on_img = np.squeeze(pixel_index[i][zeros_index_on_line[border_on_line]]) # two points
            if border_on_img.size!=4:
                continue
            # show border
            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
            # plt.imshow(border)

            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

讨论

这种不规则形状的渐变掩模应该也可以通过腐蚀膨胀操作来实现,但是腐蚀膨胀操作的系数不好控制,无法精确到单个像素。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值