跳到主要內容

A Java De-flicker Class based on Donald Graft's idea

Since QuickTime for Java has been depreciated in year 2009, and JMF (Java Media Framework) has to call for external library, there is a need to search alternative way assembling Jpeg images into a QuickTime movie.  I know Time Lapse Assembler has done a excellent job at this under Mac OS X, and it is free.  But Time Lapse Assembler fails to deal with the flickering problem commonly seen in Time-Lapse videos.  As a result, I have to find a pure-java way to write QuickTime file, and to deal with the flickering problem under Mac OS X.

Werner Randelshofer's Blog has a good solution writing QuickTime movies.  All I need to do myself is de-flickering.  Again, open-source resources help a lot.  Donald Graft kindly provides his source code of Deflicker Filter for VirtualDub.  We can learn his algorithm from the code. Graft's deflicker was written in C++.  However, what I need is Java.  So I re-write part of Graft's deflicker.  (Sorry, I still have no idea about the soften phase….)

The basic idea is simply.  As Graft wrote inside his code, "The adjustment factor is determined from a moving average of the luminance's of the past frames in the window."  Thus, what I need to do is quite simple, calculating the luminance (sum of each pixel's r+g+b divided by width*height*3) of each frame.  And then, just following Graft's idea.  Here is my deflicker filter code.



package org.sustudio.deflicker;

import java.awt.image.BufferedImage;

public class DonaldGraftDeflicker {

	private int window;
	private int scene_change_threshold;
	private int lumnData[];
	
	public DonaldGraftDeflicker(int window, int threshold) {
		this.window = window;
		this.scene_change_threshold = threshold;
		this.lumnData = new int[window];
		
		// first frame infication.
		this.lumnData[0] = 256;
	}	
			
	public BufferedImage deflicker(BufferedImage img) {
		BufferedImage image = img;
		int w = image.getWidth();
		int h = image.getHeight();
		int lum_sum = 0;
		
		// Calculate the luminance of the current frame.
		for (int y=0; y> 16) & 0xff;
				int green = (pixel >> 8) & 0xff;
				int blue = (pixel >> 0) & 0xff;
				//lum_sum += red + green + blue;
				
				lum_sum += (int) Math.ceil((0.299 * red) + (0.587 * green) + (0.114 * blue));
			}
		}
		//lum_sum /= (w * h * 3.0);
		lum_sum /= (w * h);
		System.out.print(lum_sum + "\t");
		
		// Do scene change processing.
		//boolean scene_change = false;
		if (this.scene_change_threshold < 256 &&
			this.lumnData[0] != 256 &&
			Math.abs((int)lum_sum - (int)this.lumnData[window-1]) >= this.scene_change_threshold)
		{
			this.lumnData[0] = 256;
			//scene_change = true;
		}
		
		
		// Calculate the adjustment factor for the current frame.
		// The adjustment factor is determined from a moving average
		// of the luminances of the past frames in the window.
		double scale = 1.0;
		if (this.lumnData[0] > 255) {
			for (int i=0; i 0) {
				scale = 1.0 / (double) lum_sum;
				double filt = 0.0;
				for (int i=0; i> 16) & 0xff;
				int green = (pixel >> 8) & 0xff;
				int blue = (pixel >> 0) & 0xff;
				int max = Math.max(Math.max(red, blue), green); 
				if (scale * max > 255.0) scale = 255.0 / (double)max;
				red = (int) (scale * red);
				green = (int) (scale * green);
				blue = (int) (scale * blue);
				pixel = (red & 0xff) << 16 | (green & 0xff) << 8 | (blue & 0xff) << 0;
				image.setRGB(x, y, pixel);
				lum_sum += (int) Math.ceil((0.299 * red) + (0.587 * green) + (0.114 * blue));
			}
		}
		lum_sum /= (w * h);
		System.out.println(lum_sum);
		
		return image;
		
	}
		
	private int getPixelGrayValue(int rgb) {
		int red = (rgb >> 16) & 0xff;
		int green = (rgb >> 8) & 0xff;
		int blue = (rgb >> 0) & 0xff;
		
		//return (int) Math.ceil((0.2126 * red) + (0.7152 * green) + (0.0722 * blue));
		return (int) Math.ceil((0.299 * red) + (0.587 * green) + (0.114 * blue));
	}
	
}

留言

熱門文章

窺探洋蔥的秘密:顯微鏡下的洋蔥鱗葉表皮與細胞 Onion Bulb Leaf under a microscope

在這段嘗試使用顯微鏡來拍攝的期間,「洋蔥表皮」可以說是最容易製作的玻片標本,沒有之一。只要剝開來,攤平,滴上水,蓋上玻片,基本就完事了。怪不得學校的生物課本,都會拿洋蔥表皮來設計實驗。但是想要看到鱗葉的橫切面,那就得要練練刀功,並試試你的運氣了。 洋蔥表皮是比較容易處理的樣本,這次拍攝我們就從撕皮開始。只要不是最外面那層乾掉的表皮,用哪一層都無所謂。我也沒有拿整顆洋蔥,就拿做菜切下來的地方。這樣的大小對於顯微鏡觀察來講,已經相當足夠了。 洋蔥皮剝下來後,放在滴了水的玻片上,再滴一滴水,蓋上蓋玻片。這樣一來,觀察用的玻片標本就完成了。接著放上顯微鏡的載物台,調整鏡頭到適當的高度(大約一公分),然後調整標片標本位置,調整光源,最後再進行細微的對焦,就可以開始你的觀察了! 洋蔥表皮細胞 40x 先用顯微鏡的低倍鏡來看。這架顯微鏡最低的放大倍率是40倍,可以看出洋蔥表皮的排列狀況,而且也很清楚看到表皮有深淺不一的顏色。 洋蔥表皮細胞 100x 放大到100倍,可以看到細胞裡面還有東西。透明一點的細胞會比較清楚,可以看到細胞核。有的除了細胞核外,好像還有其他的東西。 洋蔥表皮細胞 600x 繼續放大到600倍,細胞核變得更明顯了。除此之外,可以看到細胞邊緣有兩層構成。生物課本裡面介紹過,外層的是細胞壁,內層的是細胞膜。然而,在有顏色的細胞中,細胞核就沒有那麼明顯。 洋蔥鱗葉剖面 40x 看過洋蔥表皮,現在把洋蔥的鱗葉做剖面,看看裡面的細胞構成。切了很多片,終於有一片切的比較成功,可以看到上面一層薄薄的紫色表皮。這層紫色表皮就是剛剛看了很久的洋蔥表皮。中間還有帶點綠色的部位,這應該是維管束。 洋蔥鱗葉剖面 600x 直接放大到600倍,可以明顯看出紫色的表皮細胞比較扁平,底下構成洋蔥肉的透明細胞則比較大顆。問題是紫色的花青素好像只集中在表皮而已,底下那些通通沒有。但畫面的右下角,也就是靠近維管束的周邊有綠綠的,移過去看看。 洋蔥鱗葉剖面 600x 靠近維管束 在細胞內可以看到一顆顆綠綠的小球,不知道這些是不是葉綠體,或者只是有綠色色素的有色體。仔細再想想,剝開洋蔥後確實有一條條綠色的紋路,這些綠綠的小球應該就是那些紋路出現的地方。 我能看懂的部分只有這個樣子!如果有哪些高手看到,還請多多指教。

差不多食譜:手工巧克力餅乾 Chocolate Cookies

又是手工餅乾,最近一連出了兩份餅乾食譜,這個「手工巧克力餅乾」已經是第三份了。會不會有更多呢?我可以告訴大家,這是肯定的。 要怪就怪這個陰鬱的冬季雨天,哪裡都不方便去,也懶得出去。餅乾櫃空在那邊已經很久了,雖然有時候會嘴饞,但也沒有迫切去補貨的必要。反正經常開伙,平常該有的材料都會有,自己弄個成分完全透明的零食,也是個不錯的選擇。再說,用烤箱進行烘焙時,房間會變得比較乾燥,也比較溫暖。在夏天是個折磨,但到了冬天,這種感覺還滿不錯的。 話不多說,開始進行這一道「手工巧克力餅乾」的準備工作。

觀音媽.com

期末快到了,大家都深陷於考試與報告的水深火熱之中!我卻突然想起電影《小孩不笨》裡頭的「觀音媽.com」片段。在這個網路化的年代,不僅是資訊要網路化,連神明的符咒都可以網路化。即使遠在太平洋對岸,只要透過網路把符咒印出來,一樣可以「即時」地受到保佑。 請觀音娘娘保庇 觀音娘娘指點 我有一個兒子他在美國念大學 明天就要考試 請觀音娘娘幫幫忙 讓他的考試能順順利利 好 觀音娘娘說 這三張符拿去燒 燒了喝就可以了 等一下你去號面拿一些碎花瓣回家沖涼 給他喝 他現在在美國 怎麼給他喝 要郵寄也來不及了 不用緊張不用緊張 現在很先進了 你知道什麼叫做電腦嗎 電腦 你叫你的兒子去這個網頁 www.guanyinma.com(觀音媽.com) 叫他把在裡面的第三張符 和第八張符印出來 燒了沖水喝就可以了 可以回了 電影《小孩不笨》的「觀音媽.com」這個片段,可能要讓臨時抱佛腳的成語重新定義,或者說,是將神明的神聖性重新看待。在這點上,我覺得沒什麼特定宗教概念的中國人特別能夠接受這點。比起「上帝」這個全知全能的存在,中國「舉頭三尺有神明」的說法顯然要親切的多,因為神明與世人同在。用「觀音媽.com」的例子來看,神明還會用電腦給指示,寺廟或神壇化身為網頁,可以透過網頁中的符咒點選來傳遞神諭。似乎這個「神」就和「人」一樣,活在同一個維度當中。 可惜剛剛查了一下,「www.guanyingma.com」已經被註冊了,連中文的「觀音媽.com」也都沒了,要不然我還真想花些小錢把那個網域名稱買下來,真的去開個「神壇」!搞不好還能去當個「神棍」廟公! 不過威寶電信已經搶先一步用了這個概念,推出「拜媽祖專線」,只要撥打電話,在全世界任何角落都可以向媽祖拜拜。可是和電影《小孩不笨》中的片段比較起來,整體的感覺差很多。看來,還是需要一個專業生動的「廟公」,才能讓神明鮮活起來!