Java中圖像銳化操作的方法詳解
一、該圖像銳化的思想:
本文的圖像銳化是將圖像中的R,G,B的值分別從原圖像中提出,然后將分別將這三個(gè)R,G,B的值分別與卷積核進(jìn)行卷積,最終再將最后的三個(gè)卷積的結(jié)果合成為一個(gè)像素值,從而實(shí)現(xiàn)圖像的銳化效果。
二、整體的圖像銳化的代碼為:
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(), 0, 0, null);
}
public void test(Graphics graphics,String text,int width,int height,int[][] rgbOfImg) {
int[][] R ,G ,B;
int size=3;
//對(duì)于不同的功能設(shè)置不同大小的矩陣
// if(text.equals("銳化")){size = 5;}
//銳化卷積核
double[][] sharpening = {{-1,-1,-1},{-1,9,-1},{-1,-1,-1}};
// float[][] sharpening = { { -1, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1 }, { -1, -1, 25, -1, -1 },
// { -1, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1 } };
//下面開始搞卷積算法
//初始化rgb數(shù)組
R = new int[size][size];
G = new int[size][size];
B = new int[size][size];
//對(duì)應(yīng)3*3的像素格子進(jìn)行卷積計(jì)算
for(int x = 0;x < width-size+1;x++){
for(int y = 0;y < height-size+1;y++){
//設(shè)置三個(gè)值分別存儲(chǔ)r,g,b的特征值,一定要在循環(huán)內(nèi)部進(jìn)行初始化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++){
//將該點(diǎn)的RGB信息取出,放到變量中待操作
int argb = rgbOfImg[x][y];
//分段獲取其R,G,B信息
//int變量共4位32字節(jié),0位對(duì)應(yīng)透明度(A),1位對(duì)應(yīng)R值,2位對(duì)應(yīng)G值,3位對(duì)應(yīng)B值
//>>操作:將二進(jìn)制代碼向右移動(dòng),左邊空位根據(jù)符號(hào)補(bǔ)充,正號(hào)為0,負(fù)號(hào)為1,右邊超過范圍的全部舍棄
//&:二進(jìn)制位與運(yùn)算符,只有兩個(gè)變量對(duì)應(yīng)值均為1時(shí)該位才返回1,0xff表示全為1的十六進(jìn)制數(shù)(11111111),因此任何與0xff進(jìn)行位與的結(jié)果均為其本身
//先移位后取位與可以將不同值對(duì)應(yīng)的位信息取出,位與的意義是只取32字節(jié)的后8字節(jié)
R[i][j] = argb>>16 & 0xff;
G[i][j] = argb>>8 & 0xff;
B[i][j] = argb & 0xff;
}
}
if(text.equals("銳化")){
//分別對(duì)R,G,B進(jìn)行卷積操作,對(duì)應(yīng)相乘后加起來
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;
//根據(jù)該rgb值創(chuàng)建顏色對(duì)象
Color color = new Color(resultOfR, resultOfG, resultOfB);
//設(shè)置顏色,其中g(shù)raphics是圖像的畫布(見BufferedImage類與Graphics類)
graphics.setColor(color);
//畫像素點(diǎn)(drawline用來畫線,這里的起始與終點(diǎn)都是同一點(diǎn),因此可以用來畫像素點(diǎn))
//size/2用來將像素點(diǎn)賦到中心元上
graphics.drawLine(x+size/2, y+size/2, x+size/2, y+size/2);
}
}
}
// 將圖片數(shù)據(jù) 讀到數(shù)組中
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;
}
}
輸出結(jié)果:

雖然這個(gè)與原圖的差別并不大,可能由于卷積核選擇的原因。
三、關(guān)鍵代碼的解讀

該段代碼主要是要去取出RGB圖像的R,G,B值,然后分別對(duì)其R,G,B值分別進(jìn)行卷積操作,然后將卷積后的結(jié)果再重新整合成一個(gè)int的像素值,從而就實(shí)現(xiàn)了圖像的銳化處理。
當(dāng)時(shí)看這段代碼的時(shí)候,發(fā)現(xiàn)這部分不是很懂,代碼如下:
R[i][j] = argb>>16 & 0xff; G[i][j] = argb>>8 & 0xff; B[i][j] = argb & 0xff;
不過仔細(xì)分析了一下位運(yùn)算和與運(yùn)算,我發(fā)現(xiàn)這段代碼就是在分別取出R,G,B的值,因?yàn)閕nt類的像素值中是包括了a,r,g,b四個(gè)值,int是32位的,則這四個(gè)數(shù)按順序存在int中,每個(gè)數(shù)占8位。所以r對(duì)應(yīng)得二進(jìn)制需要去移動(dòng)16位才能與oxff(即1111 1111)進(jìn)行與運(yùn)算,b對(duì)應(yīng)得二進(jìn)制需要去移動(dòng)8位才能與oxff(即1111 1111)進(jìn)行與運(yùn)算,g就直接與oxff(即1111 1111)做與運(yùn)算即可,雖然這樣表達(dá)有點(diǎn)難理解,那就看下面的示意圖吧:

總結(jié)
到此這篇關(guān)于Java中圖像銳化操作的文章就介紹到這了,更多相關(guān)Java圖像銳化操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot之bootstrap和application的區(qū)別解讀
這篇文章主要介紹了SpringBoot之bootstrap和application的區(qū)別及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
Java定時(shí)器Timer與TimerTask的使用詳解
這篇文章主要介紹了Java定時(shí)器Timer與TimerTask的使用詳解,在JDK類庫(kù)中Timer主要負(fù)責(zé)計(jì)劃任務(wù)的功能,也就是在指定時(shí)間執(zhí)行某一任務(wù),執(zhí)行時(shí)候會(huì)在主線程之外起一個(gè)單獨(dú)的線程執(zhí)行指定的任務(wù),該類主要是設(shè)置任務(wù)計(jì)劃,但封裝的類是TimerTask類,需要的朋友可以參考下2023-10-10
新手學(xué)習(xí)JQuery基本操作和使用案例解析
這篇文章主要介紹了新手學(xué)習(xí)JQuery基本操作和使用案例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
Java?Mybatis使用resultMap時(shí),屬性賦值順序錯(cuò)誤的巨坑
這篇文章主要介紹了Java?Mybatis使用resultMap時(shí),屬性賦值順序錯(cuò)誤的巨坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01
springboot項(xiàng)目以jar包運(yùn)行的操作方法
公司一個(gè)springboot項(xiàng)目本來是打war包的,突然要改為打jar包,不知所措了,糾結(jié)該如何操作呢,折騰半天終于搞定了,下面把解決方案分享給大家,對(duì)springboot打jar包方式感興趣的朋友一起看看吧2021-06-06
springboot過濾器執(zhí)行兩次的解決及跨域過濾器問題
這篇文章主要介紹了springboot過濾器執(zhí)行兩次的解決及跨域過濾器問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
SpringBoot整合Redis實(shí)現(xiàn)緩存分頁(yè)數(shù)據(jù)查詢功能
類似淘寶首頁(yè),這些商品是從數(shù)據(jù)庫(kù)中查出來的嗎,答案肯定不是,本文我們就通過一個(gè)案例實(shí)操一下,首頁(yè)熱點(diǎn)數(shù)據(jù)怎么放到Redis中去查詢,感興趣的同學(xué)可以參考一下2023-06-06
聊聊Spring AOP @Before @Around @After等advice的執(zhí)行順序
這篇文章主要介紹了聊聊Spring AOP @Before @Around @After等advice的執(zhí)行順序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-02-02

