模擬油畫和鉛筆畫的濾鏡效果

油畫效果

先上未經(jīng)任何處理的原圖


原圖.png

然后使用油畫風(fēng)格的濾鏡OilPaintFilter看看效果河咽,OilPaintFilter的使用方式就一句話:)

RxImageData.bitmap(bitmap).addFilter(new OilPaintFilter()).into(image);
油畫效果.png

OilPaintFilter在處理人物圖片和風(fēng)景圖片時(shí)具有比較好的效果论咏。

OilPaintFilter的源碼如下:

import com.cv4j.core.datamodel.ColorProcessor;
import com.cv4j.core.datamodel.ImageProcessor;

/**
 * Created by Tony Shen on 2017/5/7.
 */

public class OilPaintFilter extends BaseFilter {

    private int radius = 15; // default value
    private int intensity = 40; // default value

    public OilPaintFilter() {
        this(15, 40);
    }

    public OilPaintFilter(int radius, int graylevel) {
        this.radius = radius;
        this.intensity = graylevel;
    }

    public int getRadius() {
        return radius;
    }

    public void setRadius(int radius) {
        this.radius = radius;
    }

    public int getIntensity() {
        return intensity;
    }

    public void setIntensity(int intensity) {
        this.intensity = intensity;
    }

    @Override
    public ImageProcessor doFilter(ImageProcessor src) {

        byte[][] output = new byte[3][R.length];

        int index = 0;
        int subradius = this.radius / 2;
        int[] intensityCount = new int[intensity+1];
        int[] ravg = new int[intensity+1];
        int[] gavg = new int[intensity+1];
        int[] bavg = new int[intensity+1];

        for(int i=0; i<=intensity; i++) {
            intensityCount[i] = 0;
            ravg[i] = 0;
            gavg[i] = 0;
            bavg[i] = 0;
        }

        for(int row=0; row<height; row++) {
            int ta = 0, tr = 0, tg = 0, tb = 0;
            for(int col=0; col<width; col++) {

                for(int subRow = -subradius; subRow <= subradius; subRow++)
                {
                    for(int subCol = -subradius; subCol <= subradius; subCol++)
                    {
                        int nrow = row + subRow;
                        int ncol = col + subCol;
                        if(nrow >=height || nrow < 0)
                        {
                            nrow = 0;
                        }
                        if(ncol >= width || ncol < 0)
                        {
                            ncol = 0;
                        }
                        index = nrow * width + ncol;
                        tr = R[index] & 0xff;
                        tg = G[index] & 0xff;
                        tb = B[index] & 0xff;
                        int curIntensity = (int)(((double)((tr+tg+tb)/3)*intensity)/255.0f);
                        intensityCount[curIntensity]++;
                        ravg[curIntensity] += tr;
                        gavg[curIntensity] += tg;
                        bavg[curIntensity] += tb;
                    }
                }

                // find the max number of same gray level pixel
                int maxCount = 0, maxIndex = 0;
                for(int m=0; m<intensityCount.length; m++)
                {
                    if(intensityCount[m] > maxCount)
                    {
                        maxCount = intensityCount[m];
                        maxIndex = m;
                    }
                }

                // get average value of the pixel
                int nr = ravg[maxIndex] / maxCount;
                int ng = gavg[maxIndex] / maxCount;
                int nb = bavg[maxIndex] / maxCount;
                index = row * width + col;
                output[0][index] = (byte) nr;
                output[1][index] = (byte) ng;
                output[2][index] = (byte) nb;

                // post clear values for next pixel
                for(int i=0; i<=intensity; i++)
                {
                    intensityCount[i] = 0;
                    ravg[i] = 0;
                    gavg[i] = 0;
                    bavg[i] = 0;
                }

            }
        }

        ((ColorProcessor) src).putRGB(output[0], output[1], output[2]);
        output = null;

        return src;
    }
}

其原理是使用邊緣保留濾波旭绒,邊緣保留濾波有很多種钻心,可以參考之前的一篇文章基于邊緣保留濾波實(shí)現(xiàn)人臉磨皮的算法舵稠。這里主要用的是Mean shift算法史飞,修改局部的像素權(quán)重從而實(shí)現(xiàn)圖像的像素模糊牵舱,以達(dá)到近似油畫的效果。

鉛筆畫效果

我們還開發(fā)了另一款濾鏡StrokeAreaFilter赖歌,用于模擬鉛筆畫的效果枉圃。

RxImageData.bitmap(bitmap).addFilter(new StrokeAreaFilter()).into(image);

看下效果


鉛筆畫效果.png

對(duì)于鉛筆畫而言可能有點(diǎn)牽強(qiáng),那再組合一個(gè)隨機(jī)噪聲的濾鏡試試庐冯。

RxImageData.bitmap(bitmap)
        .addFilter(new StrokeAreaFilter())
        .addFilter(new GaussianNoiseFilter())
        .into(image);
鉛筆畫效果2.png

效果也不是特別好孽亲,那再換一個(gè)USMFilter試試。

RxImageData.bitmap(bitmap)
       .addFilter(new StrokeAreaFilter())
       .addFilter(new USMFilter())
       .into(image);

終于展父,這次效果比前面兩幅效果更好了返劲。

鉛筆畫效果3.png

但是,由于是兩個(gè)濾鏡的疊加栖茉,速度會(huì)慢很多篮绿。再者,USMFilter它是繼承高斯濾鏡的吕漂。所以亲配,在實(shí)際使用中只需單獨(dú)使用StrokeAreaFilter即可,細(xì)節(jié)多少可以根據(jù)參數(shù)來(lái)調(diào)節(jié)惶凝。

總結(jié)

本文所使用的兩款濾鏡OilPaintFilter和StrokeAreaFilter都在cv4j中吼虎。

cv4jgloomyfish和我一起開發(fā)的圖像處理庫(kù),純java實(shí)現(xiàn)苍鲜,目前還處于早期的版本思灰,目前已經(jīng)更新了濾鏡的文檔。

上周末我們做了兩款濾鏡混滔,效果還算是蠻酷的洒疚,但是速度在移動(dòng)端還不夠理想歹颓,未來(lái)會(huì)想辦法對(duì)算法做一些改進(jìn),以便更好地滿足移動(dòng)端的體驗(yàn)拳亿。

該系列先前的文章:
二值圖像分析之輪廓分析
基于邊緣保留濾波實(shí)現(xiàn)人臉磨皮的算法
二值圖像分析:案例實(shí)戰(zhàn)(文本分離+硬幣計(jì)數(shù))
Java實(shí)現(xiàn)高斯模糊和圖像的空間卷積
Java實(shí)現(xiàn)圖片濾鏡的高級(jí)玩法
Java實(shí)現(xiàn)圖片的濾鏡效果

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末晴股,一起剝皮案震驚了整個(gè)濱河市愿伴,隨后出現(xiàn)的幾起案子肺魁,更是在濱河造成了極大的恐慌,老刑警劉巖隔节,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹅经,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡怎诫,警方通過查閱死者的電腦和手機(jī)瘾晃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)幻妓,“玉大人蹦误,你說我怎么就攤上這事∪饨颍” “怎么了强胰?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)妹沙。 經(jīng)常有香客問我偶洋,道長(zhǎng),這世上最難降的妖魔是什么距糖? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任玄窝,我火速辦了婚禮,結(jié)果婚禮上悍引,老公的妹妹穿的比我還像新娘恩脂。我一直安慰自己,他們只是感情好趣斤,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布俩块。 她就那樣靜靜地躺著,像睡著了一般唬渗。 火紅的嫁衣襯著肌膚如雪典阵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天镊逝,我揣著相機(jī)與錄音壮啊,去河邊找鬼。 笑死撑蒜,一個(gè)胖子當(dāng)著我的面吹牛歹啼,可吹牛的內(nèi)容都是我干的玄渗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼狸眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼藤树!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起拓萌,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤岁钓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后微王,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體屡限,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年炕倘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了钧大。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡罩旋,死狀恐怖啊央,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情涨醋,我是刑警寧澤瓜饥,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站东帅,受9級(jí)特大地震影響压固,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜靠闭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一帐我、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧愧膀,春花似錦拦键、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蟀悦,卻和暖如春媚朦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背日戈。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工询张, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人浙炼。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓份氧,卻偏偏與公主長(zhǎng)得像唯袄,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蜗帜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 不同圖像灰度不同恋拷,邊界處一般會(huì)有明顯的邊緣,利用此特征可以分割圖像厅缺。需要說明的是:邊緣和物體間的邊界并不等同蔬顾,邊緣...
    大川無(wú)敵閱讀 13,868評(píng)論 0 29
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,286評(píng)論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件店归、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,120評(píng)論 4 61
  • 近期考慮對(duì)CSS進(jìn)行一些重構(gòu)阎抒,看著以前自己的代碼整個(gè)人凌亂了酪我。于是做了一些調(diào)研消痛,看到一些不一樣的地方給大家分享一下...
    金小可閱讀 1,891評(píng)論 0 2
  • 快開學(xué)了這個(gè)夏天在炎熱中結(jié)束了。 為什么我討厭開學(xué)但是又為什么我有點(diǎn)激動(dòng) 九月的我們進(jìn)了不同的教室 認(rèn)識(shí)了不同的人...
    想要的總會(huì)來(lái)閱讀 279評(píng)論 4 7