图像油画滤镜艺术效果 python实现(超像素方法)

效果

今天在写超像素代码模块的时候偶然发现利用超像素竟然可以实现类似的油画效果,后来看了一下油画效果opencv的实现发现原理有类似之处。先来利用超像素实现的油画效果:
原图:(来自davis2017数据集的图片,将就一下)
在这里插入图片描述
处理效果
在这里插入图片描述

实现步骤

很简单两步就行了:

  • 第一步:超像素分割区域
  • 第二步:分割区域材质取样替代原像素

下面是原创代码:

from skimage.segmentation import slic,mark_boundaries
from skimage import io
import matplotlib.pyplot as plt
import numpy as np
import cv2 as cv

import time

class Texture(object):
    def __init__(self,np_matarr,idx=0,flag=1,center_ptxy=(0,0),segments=None):
        self.np_matarr=np_matarr
        self.id=idx
        self.flag=flag
        self.center_ptxy=center_ptxy
        self.colordic={'red':(255,0,0),'blue':(0,255,0),'green':(0,0,255),'default':(np_matarr[0,0,:][0],np_matarr[0,0,:][1],np_matarr[0,0,:][2])}
        self.segments=segments

    def get_reflect(self,srcimg,is_show=False,reflect_color='red'):
        ptcr=np.where(self.segments==self.id)
        color=None
        if isinstance(reflect_color,tuple): #Multitype input color
            color=reflect_color
        else:
            color=self.colordic[reflect_color]
        srcimg[ptcr[0],ptcr[1],:]=color
        if is_show:
            plt.imshow(srcimg)
            plt.show()
        return srcimg


def add_roi(backimg,logoimg,logox0,logoy0):
    backimg=backimg.copy()
    logoRs,logoCs,logoChels=logoimg.shape#算出logo的空间参数
    for y in range(logoy0,logoy0+logoRs):
            for x in range(logox0,logox0+logoCs):
                backimg[y,x,:]=logoimg[y-logoy0,x-logox0,:]
    return backimg

def roi_cutPoint(srcimg,x0,x1,y0,y1):#切割图像
    return srcimg[y0:y1,x0:x1]

def hwSet(pixels_sum,limit=300):
    w,h,fr,bc=4,3,0,0  
    for i in range(1,limit):
        w,h=4*i,3*i
        fr=bc
        bc=12*(i**2)
        #print('i={},{},{}'.format(i,fr,bc))
        if (pixels_sum<=bc)and(pixels_sum>=fr):
            break
    return h,w


def make_TextureRGB(mat_id_3,is_show=False):
    lens,_=mat_id_3.shape
    h,w=hwSet(lens)
    s=h*w
    re_texture=np.zeros([h,w,3],dtype=np.uint8)
    deta=(h*w)-lens
    deta_idxs=np.random.randint(0,(lens-1),[deta]) # 对于mat自拓充的index
    idxn,idx=0,0
    for r in range(h):
        for c in range(w):
            if idx<lens:
                re_texture[r,c,:]=mat_id_3[idx]
                idx+=1
            else:
                re_texture[r,c,:]=mat_id_3[deta_idxs[idxn]]
                idxn+=1
    if is_show:
        plt.imshow(re_texture)
        plt.show()
    return re_texture


def superPixels(img,is_show=False):
    segments = slic(img, n_segments=4000, compactness=3,enforce_connectivity=True,convert2lab=True) #compactness 越大越规则
    #450,10 sumpixels=44540
    if is_show:
        out=mark_boundaries(img,segments)*255 # make boundaries to show
        out=add_roi(img,out,0,0)
        plt.imshow(out)
        plt.show()
    return segments,segments.max()


img = io.imread("src_images/00001.jpg") # 读取图片
####


#img=roi_cutPoint(img1,299, 469, 105, 367) # 对roi x0x1y0y1区域进行裁剪
segments,blocks=superPixels(img,is_show=False)
Texture_list=[]
for idx in range(1,blocks+1):
    ptcr=np.where(segments==idx)
    arr=img[ptcr[0],ptcr[1],:]
    texture_mat=make_TextureRGB(arr,is_show=False)
    Texture_list.append(Texture(np_matarr=texture_mat,idx=idx,segments=segments))
####



imgv=img
for i in range(len(Texture_list)):
    imgv=Texture_list[i].get_reflect(imgv,is_show=False,reflect_color='default')

plt.imshow(imgv)
plt.show()

可以根据超像素的参数调节随机点的数量和规则程度,在函数slic(img, n_segments=4000, compactness=3,enforce_connectivity=True,convert2lab=True)调节

©️2020 CSDN 皮肤主题: 程序猿惹谁了 设计师:上身试试 返回首页