1. 程式人生 > >影象處理之基於畫素的影象混合

影象處理之基於畫素的影象混合

介紹幾種常見的將兩張影象混合在一起形成一張新的影象的演算法,

首先看一下下面演算法演示中要使用的兩張影象:



為了得到更好的混合效果,我選擇了兩張一樣大小的圖片。

方法一:

通過簡單對於畫素點的畫素相乘得到輸出畫素值,程式碼演示如下:

private int modeOne(int v1, int v2) {
return (v1 * v2) / 255;
}

方法一的效果如下:


方法二:

通過計算兩個畫素之和再減去方法一的輸出值,程式碼如下:

private int modeTwo(int v1, int v2) {
	return v1 + v2 - v1 * v2 / 255;
}

方法二的效果如下:


方法三:

通過畫素值128這個特殊的中值來求取輸出值,程式碼如下:

private int modeThree(int v1, int v2) {
	return (v2 < 128) ? (2 * v1 * v2 / 255):(255 - 2 * (255 - v1) * (255 - v2) / 255);
}

方法三的效果如下:


方法四:

與方法三不同,中值127.5被用在計算等式中,程式碼如下:

private int modeFour(double v1, double v2) {
  if ( v1 > 127.5 ){
      return (int)(v2 + (255.0 - v2) * ((v1 - 127.5) / 127.5) * (0.5 - Math.abs(v2-127.5)/255.0));
   }else{
      return (int)(v2 - v2 * ((127.5 -  v1) / 127.5) * (0.5 - Math.abs(v2-127.5)/255.0));
   }
}

方法四的效果如下:


方法五:

中值計算考慮,是方法一的升級版本,使得混合更加精細,程式碼如下:

private int modeFive(double v1, double v2) {
  if ( v1 > 127.5 ){
      return (int)(v2 + (255.0 - v2) * ((v1 - 127.5) / 127.5));
   }else{
      return (int)(v2 * v1 / 127.5);
   }
}

方法五的效果如下:


濾鏡原始碼如下:
package com.gloomyfish.filter.study;

import java.awt.image.BufferedImage;
/***
 * i get these blend method from html5 demo then i decide to 
 * translate these java script methods into java
 * 偶爾我也會寫中文註釋, 常見的影象混合方法
 * @author fish
 * @date 2012-11-28
 */
public class ImageBlendFilter extends AbstractBufferedImageOp {
	/** Define the blend mode */
	public final static int MULTIPLY_PIXEL = 1;
	public final static int SCREEN_PIXEL = 2;
	public final static int OVERLAY_PIXEL = 3;
	public final static int SOFTLIGHT_PIXEL = 4;
	public final static int HARDLIGHT_PIXEL = 5;
	
	private int mode;
	private BufferedImage secondImage;
	public ImageBlendFilter() {
		mode = 1;
	}

	public void setBlendMode(int mode) {
		this.mode = mode;
	}
	
	public void setSecondImage(BufferedImage image) {
		this.secondImage = image;
	}
	

	@Override
	public BufferedImage filter(BufferedImage src, BufferedImage dest) {
		checkImages(src);
		int width = src.getWidth();
        int height = src.getHeight();

        if ( dest == null )
        	dest = createCompatibleDestImage( src, null );

        int[] input1 = new int[width*height];
        int[] input2 = new int[secondImage.getWidth() * secondImage.getHeight()];
        int[] outPixels = new int[width*height];
        getRGB( src, 0, 0, width, height, input1);
        getRGB( secondImage, 0, 0, secondImage.getWidth(), secondImage.getHeight(), input2);
        int index = 0;
        int ta1 = 0, tr1 = 0, tg1 = 0, tb1 = 0;
        for(int row=0; row<height; row++) {
        	for(int col=0; col<width; col++) {
        		index = row * width + col;
        		ta1 = (input1[index] >> 24) & 0xff;
                tr1 = (input1[index] >> 16) & 0xff;
                tg1 = (input1[index] >> 8) & 0xff;
                tb1 = input1[index] & 0xff;
                int[] rgb = getBlendData(tr1, tg1, tb1, input2, row, col);
                outPixels[index] = (ta1 << 24) | (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
                
        	}
        }
        setRGB( dest, 0, 0, width, height, outPixels );
        return dest;
	}

	private int[] getBlendData(int tr1, int tg1, int tb1, int[] input,int row, int col) {
		int width = secondImage.getWidth();
        int height = secondImage.getHeight();
        if(col >= width || row >= height) {
        	return new int[]{tr1, tg1, tb1};
        }
        int index = row * width + col;
		// int ta = (input[index] >> 24) & 0xff;
        int tr = (input[index] >> 16) & 0xff;
        int tg = (input[index] >> 8) & 0xff;
        int tb = input[index] & 0xff;
        int[] rgb = new int[3];
        if(mode == 1) {
        	rgb[0] = modeOne(tr1, tr);
        	rgb[1] = modeOne(tg1, tg);
        	rgb[2] = modeOne(tb1, tb);
        }
        else if(mode == 2) {
        	rgb[0] = modeTwo(tr1, tr);
        	rgb[1] = modeTwo(tg1, tg);
        	rgb[2] = modeTwo(tb1, tb);        	
        }
        else if(mode == 3) {
        	rgb[0] = modeThree(tr1, tr);
        	rgb[1] = modeThree(tg1, tg);
        	rgb[2] = modeThree(tb1, tb);        	
        }
        else if(mode == 4) {
        	rgb[0] = modeFour(tr1, tr);
        	rgb[1] = modeFour(tg1, tg);
        	rgb[2] = modeFour(tb1, tb);        	
        }
        else if(mode == 5) {
        	rgb[0] = modeFive(tr1, tr);
        	rgb[1] = modeFive(tg1, tg);
        	rgb[2] = modeFive(tb1, tb);        	
        }
        return rgb;
	}
	
	private int modeOne(int v1, int v2) {
		return (v1 * v2) / 255;
	}
	
	private int modeTwo(int v1, int v2) {
		return v1 + v2 - v1 * v2 / 255;
	}
	
	private int modeThree(int v1, int v2) {
		return (v2 < 128) ? (2 * v1 * v2 / 255):(255 - 2 * (255 - v1) * (255 - v2) / 255);
	}
	
	private int modeFour(double v1, double v2) {
      if ( v1 > 127.5 ){
          return (int)(v2 + (255.0 - v2) * ((v1 - 127.5) / 127.5) * (0.5 - Math.abs(v2-127.5)/255.0));
       }else{
          return (int)(v2 - v2 * ((127.5 -  v1) / 127.5) * (0.5 - Math.abs(v2-127.5)/255.0));
       }
	}
	
	private int modeFive(double v1, double v2) {
      if ( v1 > 127.5 ){
          return (int)(v2 + (255.0 - v2) * ((v1 - 127.5) / 127.5));
       }else{
          return (int)(v2 * v1 / 127.5);
       }
	}

	private void checkImages(BufferedImage src) {
		int width = src.getWidth();
        int height = src.getHeight();
		if(secondImage == null || secondImage.getWidth() > width || secondImage.getHeight() > height) {
			throw new IllegalArgumentException("the width, height of the input image must be great than blend image");
		}
	}

}

如果覺得效果很有趣,請頂一下,謝謝!

轉載文章請註明

相關推薦

影象處理基於影象混合

介紹幾種常見的將兩張影象混合在一起形成一張新的影象的演算法, 首先看一下下面演算法演示中要使用的兩張影象: 為了得到更好的混合效果,我選擇了兩張一樣大小的圖片。 方法一: 通過簡單對於畫素點的畫素相乘得到輸出畫素值,程式碼演示如下: private int modeOn

影象處理基於NCC模板匹配識別

一:基本原理NCC是一種基於統計學計算兩組樣本資料相關性的演算法,其取值範圍為[-1, 1]之間,而對影象來說,每個畫素點都可以看出是RGB數值,這樣整幅影象就可以看成是一個樣本資料的集合,如果它有一個子集與另外一個樣本資料相互匹配則它的ncc值為1,表示相關性很高,如果是-

數字影象處理二維碼影象提取演算法(二)

二維碼標準: 國外:pdf417,Datamatrix,QR 國內:龍貝,漢信。 影象輸入-> 影象預處理-> 二維碼影象切割(定位)-> 二維碼影象校正-> 譯碼 譯碼:二維碼碼字提取-> 糾錯譯碼-> 資訊譯碼 糾錯譯碼:求解伴隨因

影象處理灰度模糊影象與彩色清晰影象的變換

  針對模糊影象的處理,個人覺得主要分兩條路,一種是自我激發型,另外一種屬於外部學習型。接下來我們一起學習這兩條路的具體方式。 第一種 自我激發型   基於影象處理的方法,如影象增強和影象復原,以及曾經很火的超解析度演算法。都是在不增加額外資訊的前提下的實現

影象處理積分圖應用四(基於區域性均值的影象二值化演算法)

影象處理之積分圖應用四(基於區域性均值的影象二值化演算法) 基本原理 均值法,選擇的閾值是區域性範圍內畫素的灰度均值(gray mean),該方法的一個變種是用常量C減去均值Mean,然後根據均值實現如下操作: pixel = (pixel > (mean - c)) ? ob

影象處理積分圖應用三(基於NCC快速相似度匹配演算法)

影象處理之積分圖應用三(基於NCC快速相似度匹配演算法) 基於Normalized cross correlation(NCC)用來比較兩幅影象的相似程度已經是一個常見的影象處理手段。在工業生產環節檢測、監控領域對物件檢測與識別均有應用。NCC演算法可以有效降低光照對影象比較結果的影響。而

python數字影象處理(3):影象的訪問與裁剪

圖片讀入程式中後,是以numpy陣列存在的。因此對numpy陣列的一切功能,對圖片也適用。對陣列元素的訪問,實際上就是對圖片畫素點的訪問。 彩色圖片訪問方式為: img[i,j,c] i表示圖片的行數,j表示圖片的列數,c表示圖片的通道數(RGB三通道分別對應0,1

基於清晰度的影象融合演算法(Python實現)

# -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt import cv2 from math import log from PIL import Image import d

轉《影象處理表面濾波》

本文介紹經典的表面模糊Surface Blur演算法與實現。 表面模糊是PS裡一個重要的保邊濾波器,它的演算法很簡單,公式如下所示: 主要思想還是計算當前畫素X的鄰域範圍內不同畫素的加權求和,邊緣地方的畫素,加權比較大,平滑的地方加權比較小,以此來保留邊緣資訊,平滑平坦區域; 效果如下圖所示:

影象處理---光流法

LK光流演算法公式詳解: 由於工程需要用到 Lucas-Kanade 光流,在此進行一下簡單整理(後續還會陸續整理關於KCF,PCA,SVM,最小二乘、嶺迴歸、核函式、dpm等等): 光流,簡單說也就是畫面移動過程中,影象上每個畫素的x,y位移量,比如第t幀的時候A點的位置是(x1,

影象處理積分圖應用二(快速邊緣保留濾波演算法)

影象處理之積分圖應用二(快速邊緣保留濾波演算法) 一:基本原理 傳統的影象邊緣保留濾波演算法-如高斯雙邊模糊、Mean-Shift模糊等計算複雜、效率比較低,雖然有各種手段優化或者快速計算方法,當時演算法相對一般碼農來說理解起來比較費勁,不是一個的選擇,而通過積分影象實現區域性均方差

影象處理積分圖應用一(半徑無關的快速模糊演算法)

影象處理之積分影象應用一(半徑無關的快速模糊演算法) 一:基本原理概述 傳統的影象空間域卷積模糊演算法,當視窗大小改變時卷積模糊時間也會變化,而且隨著視窗尺寸越大計算量也越大,演算法執行時間約越長。在很多時候無法滿足實時性要求。而基於積分影象可以實現對視窗區域和大小的快速計算,把傳統卷積

影象處理積分圖演算法

影象處理之積分圖演算法 一:積分圖來源與發展 積分影象是Crow在1984年首次提出,是為了在多尺度透視投影中提高渲染速度。隨後這種技術被應用到基於NCC的快速匹配、物件檢測和SURF變換中、基於統計學的快速濾波器等方面。積分影象是一種在影象中快速計算矩形區域和的方法,這種演算法主要優點

數字影象處理空間域濾波和銳化(Octave實現)

濾波這一概念可以結合數字訊號處理這一領域中的濾波。而在數字影象處理中濾波可以分為空間域濾波和頻率域濾波。這篇博文主要來學習下空間域濾波。 空間域濾波機理 *空間濾波器由一個鄰域(典型的是一個較小的矩形)構成,對該鄰域所包圍的畫素按照一定的操作計算出目標畫素的值,這一過程就是空

影象處理影象基本變化(平移、縮放、旋轉)(Octave實現)

在模式識別及計算機視覺中,要經常進行影象的變化。 例如:在識別手寫數字中,我們可能在廣泛應用中要求所有的圖片都是20*20這麼好的規格。所以,我們就需要進行縮放來達到目的。 今天來總結下學到的影象的基本變換。 首先我們計 (w,v) (w,v)為源影象的

數字影象處理直方圖均衡化(Octave)

直方圖的均衡化是什麼呢? 舉個簡單的例子:在一個圓中有很多石頭,都集中在圓心附近,對其均衡化就是讓這些石頭儘可能的均勻分佈在圓這個區域內。 並且還有一個原則:如果石頭A在原來狀態下距離圓心的距離在所有石頭是第4位,那麼均衡化後仍然是第4位,相對順序不能變。(大概就是一個拉的更寬了)

影象處理特徵提取

知乎上看到一個話題——目前火熱的 Deep Learning 會滅絕傳統的 SIFT / SURF 特徵提取方法嗎? 由於之前研究過SIFT和HOG這兩種傳統的特徵提取方法,故本篇文章先對SIFT和HOG作一綜述,並比較二者優缺點。之後,將SIFT和HOG同神經網路特徵提取做一對比,淺談對上

影象處理gamma校正

轉載自:淇淇寶貝:影象處理之gamma校正 1 gamma校正背景   在電視和圖形監視器中,映象管發生的電子束及其生成的影象亮度並不是隨映象管的輸入電壓線性變化,電子流與輸入電壓相比是按照指數曲線變化的,輸入電壓的指數要大於電子束的指數。這說明暗區的訊號要比實際情況更暗,而亮區要

載入影象和遍歷(OpenCV)

#include <iostream> using namespace std; #include <opencv2\opencv.hpp> using namespace cv; void main() { Mat imgMat = imread("0_depth.png

影象處理修復

對黑色空洞區域進行處理,輸出影象尺寸為[768,1024,3] 然後利用以下得到影象 水平太菜,改了兩天才改成這個鬼樣子 後來想到col=768,row=1024,應該是768行,1024列,然後把順序顛倒過來了 還是有問題繼續處理: 發現是RGB三