Java中影象銳化操作的方法詳解
阿新 • • 發佈:2020-11-10
一、該影象銳化的思想:
本文的影象銳化是將影象中的R,G,B的值分別從原影象中提出,然後將分別將這三個R,B的值分別與卷積核進行卷積,最終再將最後的三個卷積的結果合成為一個畫素值,從而實現影象的銳化效果。
二、整體的影象銳化的程式碼為:
package com.yf1105; import java.awt.Color; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JFrame; public class ImageTest extends JFrame{ public static void main(String[] args) { new ImageTest(); } public ImageTest() { setSize(1000,700); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } @Override public void paint(Graphics g) { super.paint(g); int[][] rgbOfImg = getImagePixel("image/3.jpg"); test(g,"銳化",rgbOfImg.length,rgbOfImg[0].length,rgbOfImg); // g.drawImage(new ImageIcon("img/hk.jpg").getImage(),null); } public void test(Graphics graphics,String text,int width,int height,int[][] rgbOfImg) { int[][] R,B; int size=3; //對於不同的功能設定不同大小的矩陣 // if(text.equals("銳化")){size = 5;} //銳化卷積核 double[][] sharpening = {{-1,-1,-1},{-1,9,-1}}; // float[][] sharpening = { { -1,-1 },{ -1,25,// { -1,-1 } }; //下面開始搞卷積演算法 //初始化rgb陣列 R = new int[size][size]; G = new int[size][size]; B = new int[size][size]; //對應3*3的畫素格子進行卷積計算 for(int x = 0;x < width-size+1;x++){ for(int y = 0;y < height-size+1;y++){ //設定三個值分別儲存r,g,b的特徵值,一定要在迴圈內部進行初始化0,這樣才能每次有不同的值 int resultOfR = 0; int resultOfG = 0; int resultOfB = 0; //將格子的rgb值都取出,便於之後的卷積操作 for(int j = 0;j <size;j++){ for(int i = 0;i < size;i++){ //將該點的RGB資訊取出,放到變數中待操作 int argb = rgbOfImg[x][y]; //分段獲取其R,B資訊 //int變數共4位32位元組,0位對應透明度(A),1位對應R值,2位對應G值,3位對應B值 //>>操作:將二進位制程式碼向右移動,左邊空位根據符號補充,正號為0,負號為1,右邊超過範圍的全部捨棄 //&:二進位制位與運算子,只有兩個變數對應值均為1時該位才返回1,0xff表示全為1的十六進位制數(11111111),因此任何與0xff進行位與的結果均為其本身 //先移位後取位與可以將不同值對應的位資訊取出,位與的意義是隻取32位元組的後8位元組 R[i][j] = argb>>16 & 0xff; G[i][j] = argb>>8 & 0xff; B[i][j] = argb & 0xff; } } if(text.equals("銳化")){ //分別對R,B進行卷積操作,對應相乘後加起來 for(int j = 0;j < size;j++){ for(int i = 0;i < size;i++){ resultOfR += (int)(sharpening[i][j]*R[i][j]); } } for(int i = 0;i < size;i++){ for(int j = 0;j < size;j++){ resultOfG += (int)(sharpening[i][j]*G[i][j]); } } for(int i = 0;i < size;i++){ for(int j = 0;j < size;j++){ resultOfB += (int)(sharpening[i][j]*B[i][j]); } } } //如果超過了rgb的界限(0-255),將其按照最大值或最小值處理 if(resultOfR > 255)resultOfR = 255; if(resultOfR < 0)resultOfR = 0; if(resultOfG > 255)resultOfG = 255; if(resultOfG < 0)resultOfG = 0; if(resultOfB > 255)resultOfB = 255; if(resultOfB < 0)resultOfB = 0; //根據該rgb值建立顏色物件 Color color = new Color(resultOfR,resultOfG,resultOfB); //設定顏色,其中graphics是影象的畫布(見BufferedImage類與Graphics類) graphics.setColor(color); //畫畫素點(drawline用來畫線,這裡的起始與終點都是同一點,因此可以用來畫畫素點) //size/2用來將畫素點賦到中心元上 graphics.drawLine(x+size/2,y+size/2,x+size/2,y+size/2); } } } // 將圖片資料 讀到陣列中 public int[][] getImagePixel(String image) { BufferedImage bi = null; File file = new File(image); try { bi = ImageIO.read(file); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } int w = bi.getWidth(); int h = bi.getHeight(); int imgindex[][] = new int[w][h]; for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { int rgb = bi.getRGB(i,j); imgindex[i][j] = rgb; System.out.print(" " + rgb); } System.out.println(); } return imgindex; } }
輸出結果:
雖然這個與原圖的差別並不大,可能由於卷積核選擇的原因。
三、關鍵程式碼的解讀
該段程式碼主要是要去取出RGB影象的R,G,B值,然後分別對其R,G,B值分別進行卷積操作,然後將卷積後的結果再重新整合成一個int的畫素值,從而就實現了影象的銳化處理。
當時看這段程式碼的時候,發現這部分不是很懂,程式碼如下:
R[i][j] = argb>>16 & 0xff; G[i][j] = argb>>8 & 0xff; B[i][j] = argb & 0xff;
不過仔細分析了一下位運算和與運算,我發現這段程式碼就是在分別取出R,G,B的值,因為int類的畫素值中是包括了a,r,g,b四個值,int是32位的,則這四個數按順序存在int中,每個數佔8位。所以r對應得二進位制需要去移動16位才能與oxff(即1111 1111)進行與運算,b對應得二進位制需要去移動8位才能與oxff(即1111 1111)進行與運算,g就直接與oxff(即1111 1111)做與運算即可,雖然這樣表達有點難理解,那就看下面的示意圖吧:
總結
到此這篇關於Java中影象銳化操作的文章就介紹到這了,更多相關Java影象銳化操作內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!