經常使用的像素操做算法:Resize、Flip、Rotate

Resize

圖像縮放是把原圖像按照目標尺寸放大或者縮小,是圖像處理的一種。java

圖像縮放有多種算法。最爲簡單的是最臨近插值算法,它是根據原圖像和目標圖像的尺寸,計算縮放的比例,而後根據縮放比例計算目標像素所依據的原像素,過程當中天然會產生小數,這時就採用四捨五入,取與這個點最相近的點。git

除此以外,還有雙線性插值算法。github

雙線性插值,又稱爲雙線性內插。在數學上,雙線性插值是有兩個變量的插值函數的線性插值擴展,其核心思想是在兩個方向分別進行一次線性插值。算法

其公式以下: f(i+u,j+v) =(1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)函數

其中U和V表示浮點座標的小數部分,顯然離目標點距離越近的點的權重越大,這也正符合目標點的值與離他最近的點最接近這一事實。spa

cv4j的resize目前支持這兩種算法。經過Resize類的源碼,能夠看到有兩個常量.net

public final static int NEAREST_INTEPOLATE = 1; // 最臨近插值算法
	public final static int BILINE_INTEPOLATE = 2;     // 雙線性插值算法
複製代碼

使用最臨近插值算法,將原圖縮小到0.75倍。3d

CV4JImage cv4jImage = new CV4JImage(bitmap);
        ImageProcessor imageProcessor = cv4jImage.getProcessor();

        Resize resize = new Resize(0.75f);

        imageProcessor = resize.resize(imageProcessor,Resize.NEAREST_INTEPOLATE);

        if (imageProcessor!=null) {
            CV4JImage resultCV4JImage = new CV4JImage(imageProcessor.getWidth(), imageProcessor.getHeight(), imageProcessor.getPixels());
            result1.setImageBitmap(resultCV4JImage.getProcessor().getImage().toBitmap());
        }
複製代碼

使用雙線性插值算法,將原圖放大2倍。code

cv4jImage = new CV4JImage(bitmap);
        ImageProcessor imageProcessor2 = cv4jImage.getProcessor();

        resize = new Resize(2f);

        imageProcessor2 = resize.resize(imageProcessor,Resize.BILINE_INTEPOLATE);

        if (imageProcessor2!=null) {
            CV4JImage resultCV4JImage = new CV4JImage(imageProcessor2.getWidth(), imageProcessor2.getHeight(), imageProcessor2.getPixels());
            result2.setImageBitmap(resultCV4JImage.getProcessor().getImage().toBitmap());
        }
複製代碼

效果以下: orm

圖像縮放.png

Flip

Flip是翻轉的意思,也被稱爲鏡像變換。又能夠分爲水平鏡像和垂直鏡像,水平鏡像即將圖像左半部分和右半部分以圖像豎直中軸線爲中心軸進行兌換,而豎直鏡像則是將圖像上半部分和下半部分以圖像水平中軸線爲中心軸進行兌換。

flip的算法很簡單

public final static int FLIP_VERTICAL = -1;
	public final static int FLIP_HORIZONTAL = 1;
	
	public static void flip(ImageProcessor processor, int option) {
		int width = processor.getWidth();
        int height = processor.getHeight();
        int ch = processor.getChannels();
        int index1 = 0;
        int index2 = 0;
        int total = width*height;
        byte[][] output = new byte[ch][total];
        for(int row=0; row<height; row++) {
        	for(int col=0; col<width; col++) {
        		index1 = row*width+col;
        		if(option == FLIP_HORIZONTAL) {
        			index2 = row*width + width-col-1;
        		} else if(option == FLIP_VERTICAL){
        			index2 = (height-row-1)*width + col;
        		} else {
        			throw new CV4JException("invalid option : " + option);
        		}
        		for(int i=0; i<ch; i++) {
        			output[i][index2] = processor.toByte(i)[index1];
        		}
        	}
        }
        if(ch == 3) {
        	((ColorProcessor) processor).putRGB(output[0], output[1], output[2]);
        } else {
        	((ByteProcessor) processor).putGray(output[0]);
        }
	}
複製代碼

實現具體的左右翻轉

CV4JImage cv4jImage = new CV4JImage(bitmap);
        ImageProcessor imageProcessor = cv4jImage.getProcessor();

        Flip.flip(imageProcessor,Flip.FLIP_HORIZONTAL);

        if (imageProcessor!=null) {
            CV4JImage resultCV4JImage = new CV4JImage(imageProcessor.getWidth(), imageProcessor.getHeight(), imageProcessor.getPixels());
            result1.setImageBitmap(resultCV4JImage.getProcessor().getImage().toBitmap());
        }
複製代碼

實現具體的上下翻轉

cv4jImage = new CV4JImage(bitmap);
        ImageProcessor imageProcessor2 = cv4jImage.getProcessor();

        Flip.flip(imageProcessor2,Flip.FLIP_VERTICAL);

        if (imageProcessor2!=null) {
            CV4JImage resultCV4JImage = new CV4JImage(imageProcessor2.getWidth(), imageProcessor2.getHeight(), imageProcessor2.getPixels());
            result2.setImageBitmap(resultCV4JImage.getProcessor().getImage().toBitmap());
        }
複製代碼

效果以下:

圖像翻轉.png

Rotate

圖像旋轉是指圖像以某一點爲中心旋轉必定的角度,造成一幅新的圖像的過程。固然這個點一般就是圖像的中心。既然是按照中心旋轉,天然會有這樣一個屬性:旋轉前和旋轉後的點離中心的位置不變。

圖像的旋轉是圖像幾何變換的一種,旋轉先後的圖像的像素的RGB都是沒有改變的,改變的只是每個像素的所在位置。

cv4j提供兩種旋轉的算法:NormRotate和FastRotate

下面以NormRotate爲例,使用起來很簡單,旋轉120度,背景爲紅色。

CV4JImage cv4jImage = new CV4JImage(bitmap);
        ImageProcessor imageProcessor = cv4jImage.getProcessor();

        NormRotate normRotate = new NormRotate();
        imageProcessor = normRotate.rotate(imageProcessor,120, Scalar.rgb(255,0,0));

        if (imageProcessor!=null) {
            CV4JImage resultCV4JImage = new CV4JImage(imageProcessor.getWidth(), imageProcessor.getHeight(), imageProcessor.getPixels());
            result.setImageBitmap(resultCV4JImage.getProcessor().getImage().toBitmap());
        }
複製代碼

效果以下:

圖像旋轉.png

總結

cv4j 是gloomyfish和我一塊兒開發的圖像處理庫,純java實現,咱們已經分離了一個Android版本和一個Java版本。

像素操做是 cv4j 的基本功能之一,本文介紹了三種常見的變換。咱們能夠經過圖像的Resize、Flip、Rotate變換來豐富圖片數據的多樣性。

若是您想看該系列先前的文章能夠訪問下面的文集: www.jianshu.com/nb/10401400

相關文章
相關標籤/搜索