初学JAVA项目(三、槑图秀秀)
初學JAVA項目(三、槑圖秀秀)
- Java槑圖秀秀
- 前言
- 一、圖像處理
- 二、技術難點
- 1.開發過程
- 2.卷積(CNN)
- 2.均衡化濾鏡
- 2.其他濾鏡
- 總結
Java槑圖秀秀
前言
本次項目學習目標:
主要通過以項目為導向學習數組、圖像算法
一、圖像處理
百度百科:圖像算法是指對圖像進行處理所用的的算法。包括對圖像去噪、圖像變換、圖像分析、圖像壓縮、圖像增強、圖像模糊處理等。
界面截圖:
二、技術難點
1.開發過程
?????原有框架的基礎上添加實現。如下功能
2.卷積(CNN)
?????人工智能里的卷積神經網絡(CNN)是最近今年最火的圖像技術之一。
?????卷積其實就是近視眼——不能精確地看清每個像素,而是把它和周圍的像素模模糊糊地看作一團,就好像得了近視一樣。例如下面左圖,卷積之后就變成了右圖:
?????如何實現這種效果呢?以卷積半徑等于1為例,也就是跟周圍距離為1的其他像素混作一團,具體的做法是:對于新圖像中位于r行和c列,即(r,c)的像素,RGB三個顏色通道的值不是直接復制原圖像中的像素,而要取原圖像中從(r-1,c-1)至(r+1,c+1)一共9個像素的平均值(向下取整)。
?????例如原圖像為下圖的話:
?????加粗顯示的(1,2)位置的像素,卷積前是(32,67,12);按照卷積半徑1進行卷積后,RGB三個通道的值就會變為:
?????????????????????????R = (84+74+16+66+32+95+28+47+31)/9 = 52
?????????????????????????G = (22+38+17+53+67+65+49+21+41)/9 = 41
?????????????????????????B = (99+69+18+88+12+35+31+94+51)/9 = 55
?????也就是黃色框圈起來的9個像素取平均值。
代碼如下:
/** * 卷積 */ public GImage convolution(GImage source) { int[][] pixelArray = source.getPixelArray(); int height = pixelArray.length; int width = pixelArray[0].length; int[][] newPixelArray = new int[height][width]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { newPixelArray[y][x] = newPixel(pixelArray, x, y); } } return new GImage(newPixelArray); } /** * 計算某個像素點的卷積像素 * CONVOLUTION_RADIUS 卷積半徑 * * @param pixelArray 原始像素數組 * @param x 二維數組索引 * @param y 一維數組索引 * @return 卷積后新的像素 */ private int newPixel(int[][] pixelArray, int x, int y) { int height = pixelArray.length; int width = pixelArray[0].length; //設置三個值分別存儲r,g,b的特征值,一定要在循環內部進行初始化0,這樣才能每次有不同的值 int resultOfR = 0; int resultOfG = 0; int resultOfB = 0; // 計算卷積時,使用的像素點數 int count = 0; // 當前像素點的卷積范圍 int xMin = Math.max(x - CONVOLUTION_RADIUS, 0); int xMax = Math.min(x + CONVOLUTION_RADIUS, width - 1); int yMin = Math.max(y - CONVOLUTION_RADIUS, 0); int yMax = Math.min(y + CONVOLUTION_RADIUS, height - 1); for (int i = yMin; i <= yMax; i++) { for (int j = xMin; j <= xMax; j++) { resultOfR += GImage.getRed(pixelArray[i][j]); resultOfG += GImage.getGreen(pixelArray[i][j]); resultOfB += GImage.getBlue(pixelArray[i][j]); count++; } } return GImage.createRGBPixel(resultOfR / count, resultOfG / count, resultOfB / count); }2.均衡化濾鏡
????均衡化是一種主要應用于灰度圖片的技術,可以增強畫面的對比度。
????均衡做法其實也很簡單:
1、計算每個像素的亮度
2、根據亮度調整每個像素的顏色
均衡計算亮度
????像素的亮度是根據RGB通道值計算的,新建一個接口類 PSAlgorithmsInterface,實現代碼如下:
public interface PSAlgorithmsInterface {public static final int CONVOLUTION_RADIUS = 1;public GImage flipHorizontal(GImage source);public GImage rotateCounterclockwise(GImage source);public GImage rotateClockwise(GImage source);public GImage greenScreen(GImage source);public GImage negative(GImage source);public GImage crop(GImage source, int cropX, int cropY, int cropWidth, int cropHeight);public GImage convolution(GImage source);/* 計算圖片亮度 */public default int computeLuminosity(int r, int g, int b) {return GMath.round(0.299 * r + 0.587 * g + 0.114 * b);} }????然后可以像下面這樣直接使用:
int luminosity = computeLuminosity(red, green, blue);????這個函數算出的是一個0-255之間的整數,代表該像素RGB所對應的亮度。
調整顏色
????調整顏色時,R、G、B三個通道會被調整為相等的值,都等于???? 255 * 亮度小于等于當前像素的像素個數 / 整張圖片的像素數量 ???,小數結果向下取整即可。
????舉個例子。假如有一張20x10的圖片,總共200個像素。其中亮度為0的有三個像素,亮度為1的有五個像素,亮度為2的有零個像素,亮度為3的有兩個像素。那么
- 對于亮度為0的三個像素,整張圖片亮度小于等于0的也是這三個像素,所以調整過后R=G=B=255*3/200=3,也就是RGB三個通道都改為3就可以了。
- 對于亮度為1的五個像素,整張圖片亮度小于等于1的有3+5=8個像素,所以調整過后R=G=B=255*8/200=10,也就是RGB三個通道都改為10就可以了。
- 原圖沒有亮度為2的像素,直接跳過。
- 對于亮度為3的兩個像素,整張圖片亮度小于等于2的有3+5+0+2=10個像素,所以調整過后R=G=B=255*10/200=12,也就是RGB三個通道都改為12就可以了。
- 以此類推。
代碼如下:
/** * 均衡化 */ public GImage equalization(GImage source) { int[][] pixelArray = source.getPixelArray(); int equalHeight = pixelArray.length; int equalWidth = pixelArray[0].length; int allPixel = equalHeight * equalWidth; int[] a = new int[256]; for (int row = 0; row < equalHeight; row++) { for (int col = 0; col < equalWidth; col++) { int pixel = pixelArray[row][col]; int r = GImage.getRed(pixel); int g = GImage.getGreen(pixel); int b = GImage.getBlue(pixel); int luminosity = computeLuminosity(r, g, b); //遍歷luminosity ,每出現一次相同的值就+1 a[luminosity]++; } } for (int i = 0; i < 255; i++) { a[i + 1] = a[i] + a[i + 1]; a[i] = 255 * a[i] / allPixel; } for (int row = 0; row < equalHeight; row++) { for (int col = 0; col < equalWidth; col++) { int pixel = pixelArray[row][col]; int r = GImage.getRed(pixel); int g = GImage.getGreen(pixel); int b = GImage.getBlue(pixel); int Result = computeLuminosity(r, g, b); int newPixel = GImage.createRGBPixel(a[Result], a[Result], a[Result]); pixelArray[row][col] = newPixel; } } // TODO return new GImage(pixelArray); }2.其他濾鏡
大致的方法都一樣,知識其中的核心算法有些許不同,參考其他博客實現大部分濾鏡效果:
Java圖像處理:灰度、二值化、浮雕、去色、反向、懷舊、放大鏡等
https://blog.csdn.net/m0_51673807/article/details/110588972
【圖像處理】中的“濾鏡算法”:灰度、黑白、反向、去色、單色、高斯模糊、懷舊、連環畫
https://blog.csdn.net/weixin_42346564/article/details/95909449
總結
????通過這個項目主要學習數組、圖像算法等基礎概念,做項目的過程發現自己經常卡在算法方面,懂算法原理但是不懂如何在代碼中實現它,大部分都是參考別人的代碼完成,所以基礎知識改補還是要補,先從Java基礎視頻開始看起把,訂個目標:項目之余每天三個小時視頻+實操學習。
全部代碼(待改進~)
https://gitee.com/liaodemo/ps
部分方法代碼:
import acm.graphics.*;import java.awt.*;public class PSAlgorithms implements PSAlgorithmsInterface {//逆時針public GImage rotateCounterclockwise(GImage source) {/************************************************* 旋轉前,舊圖片的信息************************************************/int[][] oldPixelArray = source.getPixelArray(); // 舊圖片數組int oldHeight = oldPixelArray.length; // 舊圖片高度int oldWidth = oldPixelArray[0].length; // 舊圖片寬度/************************************************* 旋轉前,舊圖片的信息************************************************/int newHeight = oldWidth; // 新圖片高度等于舊圖片寬度int newWidth = oldHeight; // 新圖片寬度等于舊圖片高度int[][] newPixelArray = new int[newHeight][newWidth]; // 為新圖片新建一個數組,行數是newHeight,列數是newWidth/************************************************* 新舊數組的像素對應關系************************************************/for (int yNew = 0; yNew < newHeight; yNew++) { //新圖片高度大于0,yNew加1for (int xNew = 0; xNew < newWidth; xNew++) { //新圖片寬度大于0,xNew加1int yOld = xNew; //逆旋轉前后舊圖片寬(x)等于給新圖片高(y)int xOld = oldWidth - yNew - 1; //逆旋轉前后新圖片高(x)為舊圖的寬減去yNew-1newPixelArray[yNew][xNew] = oldPixelArray[yOld][xOld];}}return new GImage(newPixelArray);}public GImage rotateClockwise(GImage source) {/************************************************* 旋轉前,舊圖片的信息************************************************/int[][] oldPixelArray = source.getPixelArray(); // 舊圖片數組int oldHeight = oldPixelArray.length; // 舊圖片高度int oldWidth = oldPixelArray[0].length; // 舊圖片寬度/************************************************* 旋轉前,舊圖片的信息************************************************/int newHeight = oldWidth; // 新圖片高度等于舊圖片寬度int newWidth = oldHeight; // 新圖片寬度等于舊圖片高度int[][] newPixelArray = new int[newHeight][newWidth]; // 為新圖片新建一個數組,行數是newHeight,列數是newWidth/************************************************* 新舊數組的像素對應關系************************************************/for (int yNew = 0; yNew < newHeight; yNew++) {for (int xNew = 0; xNew < newWidth; xNew++) {int yOld = oldHeight - xNew - 1;int xOld = yNew;newPixelArray[yNew][xNew] = oldPixelArray[yOld][xOld];}}return new GImage(newPixelArray);}//水平翻轉public GImage flipHorizontal(GImage source) {/************************************************* 旋轉前,舊圖片的信息************************************************/int[][] oldPixelArray = source.getPixelArray(); // 舊圖片數組int oldHeight = oldPixelArray[0].length; // 舊圖片高度int oldWidth = oldPixelArray.length; // 舊圖片寬度/************************************************* 旋轉前,舊圖片的信息************************************************/int newHeight = oldWidth; // 新圖片高度等于舊圖片寬度int newWidth = oldHeight; // 新圖片寬度等于舊圖片高度int[][] newPixelArray = new int[newHeight][newWidth]; // 為新圖片新建一個數組,行數是newHeight,列數是newWidth/************************************************* 新舊數組的像素對應關系************************************************/for (int yNew = 0; yNew < newHeight; yNew++) {for (int xNew = 0; xNew < newWidth; xNew++) {int yOld = yNew;int xOld = oldHeight - xNew - 1;newPixelArray[yNew][xNew] = oldPixelArray[yOld][xOld];}}return new GImage(newPixelArray);}/*** 二值化*/public GImage bastardization(GImage source) {int[][] pixelArray = source.getPixelArray();int inverseHeight = pixelArray.length;int inverseWidth = pixelArray[0].length;for (int row = 0; row < inverseHeight; row++) {for (int col = 0; col < inverseWidth; col++) {int pixel = pixelArray[row][col];int r = GImage.getRed(pixel);int g = GImage.getGreen(pixel);int b = GImage.getBlue(pixel);int gray = (int) (0.299 * r + 0.587 * g + 0.114 * b);if (gray > 170) {gray = 255;} else {gray = 0;}int newPixel = GImage.createRGBPixel(gray, gray, gray);pixelArray[row][col] = newPixel;}}return new GImage(pixelArray);}/*** 反相*/public GImage negative(GImage source) {int[][] pixelArray = source.getPixelArray();int inverseHeight = pixelArray.length;int inverseWidth = pixelArray[0].length;for (int row = 0; row < inverseHeight; row++) {for (int col = 0; col < inverseWidth; col++) {int pixel = pixelArray[row][col];int r = GImage.getRed(pixel);int g = GImage.getGreen(pixel);int b = GImage.getBlue(pixel);//255減去rgb三原色int newPixel = GImage.createRGBPixel(255 - r, 255 - g, 255 - b);pixelArray[row][col] = newPixel;}}return new GImage(pixelArray);}/*** 綠布*/public GImage greenScreen(GImage source) {int[][] pixelArray = source.getPixelArray();int inverseHeight = pixelArray.length;int inverseWidth = pixelArray[0].length;//創建一個透明像素int transparentPixel = GImage.createRGBPixel(0, 0, 0, 0);for (int row = 0; row < inverseHeight; row++) {for (int col = 0; col < inverseWidth; col++) {int pixel = pixelArray[row][col];int r = GImage.getRed(pixel);int g = GImage.getGreen(pixel);int b = GImage.getBlue(pixel);//像素的綠色(G)至少是紅色(R)和藍色(B)中較大值的兩倍,就把這個像素當作綠色if (g >= Math.max(r, b) * 2) {pixelArray[row][col] = transparentPixel;}}}// TODOreturn new GImage(pixelArray);}/*** 卷積*/public GImage convolution(GImage source) {int[][] pixelArray = source.getPixelArray();int height = pixelArray.length;int width = pixelArray[0].length;int[][] newPixelArray = new int[height][width];for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {newPixelArray[y][x] = newPixel(pixelArray, x, y);}}return new GImage(newPixelArray);}/*** 計算某個像素點的卷積像素* CONVOLUTION_RADIUS 卷積半徑** @param pixelArray 原始像素數組* @param x 二維數組索引* @param y 一維數組索引* @return 卷積后新的像素*/private int newPixel(int[][] pixelArray, int x, int y) {int height = pixelArray.length;int width = pixelArray[0].length;//設置三個值分別存儲r,g,b的特征值,一定要在循環內部進行初始化0,這樣才能每次有不同的值int resultOfR = 0;int resultOfG = 0;int resultOfB = 0;// 計算卷積時,使用的像素點數int count = 0;// 當前像素點的卷積范圍int xMin = Math.max(x - CONVOLUTION_RADIUS, 0);int xMax = Math.min(x + CONVOLUTION_RADIUS, width - 1);int yMin = Math.max(y - CONVOLUTION_RADIUS, 0);int yMax = Math.min(y + CONVOLUTION_RADIUS, height - 1);for (int i = yMin; i <= yMax; i++) {for (int j = xMin; j <= xMax; j++) {resultOfR += GImage.getRed(pixelArray[i][j]);resultOfG += GImage.getGreen(pixelArray[i][j]);resultOfB += GImage.getBlue(pixelArray[i][j]);count++;}}return GImage.createRGBPixel(resultOfR / count, resultOfG / count, resultOfB / count);}/*** 裁剪圖片,裁剪后僅保留選區內容,其他全部刪掉** @param source 要被裁剪的原始圖片* @param cropX 選區左上角的x坐標* @param cropY 選區左上角的y坐標* @param cropWidth 選區的寬度* @param cropHeight 選區的高度* @return 裁剪后的圖片*/public GImage crop(GImage source, int cropX, int cropY, int cropWidth, int cropHeight) {int[][] oldPixelArray = source.getPixelArray();int[][] newPixelArray = new int[cropHeight][cropWidth];for (int X = 0; X < cropWidth; X++) {for (int Y = 0; Y < cropHeight; Y++) {int yOld = cropY + Y;int xOld = cropX + X;newPixelArray[Y][X] = oldPixelArray[yOld][xOld];}}return new GImage(newPixelArray);}/*** 均衡化*/public GImage equalization(GImage source) {int[][] pixelArray = source.getPixelArray();int equalHeight = pixelArray.length;int equalWidth = pixelArray[0].length;int allPixel = equalHeight * equalWidth;int[] a = new int[256];for (int row = 0; row < equalHeight; row++) {for (int col = 0; col < equalWidth; col++) {int pixel = pixelArray[row][col];int r = GImage.getRed(pixel);int g = GImage.getGreen(pixel);int b = GImage.getBlue(pixel);int luminosity = computeLuminosity(r, g, b);//遍歷luminosity ,每出現一次相同的值就+1a[luminosity]++;}}for (int i = 0; i < 255; i++) {a[i + 1] = a[i] + a[i + 1];a[i] = 255 * a[i] / allPixel;}for (int row = 0; row < equalHeight; row++) {for (int col = 0; col < equalWidth; col++) {int pixel = pixelArray[row][col];int r = GImage.getRed(pixel);int g = GImage.getGreen(pixel);int b = GImage.getBlue(pixel);int Result = computeLuminosity(r, g, b);int newPixel = GImage.createRGBPixel(a[Result], a[Result], a[Result]);pixelArray[row][col] = newPixel;}}// TODOreturn new GImage(pixelArray);}/*** 利用懷舊濾鏡公式實現圖像處理*/public GImage nostalgia(GImage source) {int[][] pixelArray = source.getPixelArray();int inverseHeight = pixelArray.length;int inverseWidth = pixelArray[0].length;for (int row = 0; row < inverseHeight; row++) {for (int col = 0; col < inverseWidth; col++) {int pixel = pixelArray[row][col];int r = GImage.getRed(pixel);int g = GImage.getGreen(pixel);int b = GImage.getBlue(pixel);int[] rgb = new int[3];rgb[0] = (int) (0.393 * r + 0.769 * g + 0.189 * b);rgb[1] = (int) (0.349 * r + 0.686 * g + 0.168 * b);rgb[2] = (int) (0.272 * r + 0.534 * g + 0.131 * b);for (int m = 0; m < 3; m++) {if (rgb[m] > 255)rgb[m] = 255;}int newPixel = GImage.createRGBPixel(rgb[0], rgb[1], rgb[2]);pixelArray[row][col] = newPixel;}}return new GImage(pixelArray);}/*** 去色*/public GImage decolor(GImage source) {int[][] pixelArray = source.getPixelArray();int inverseHeight = pixelArray.length;int inverseWidth = pixelArray[0].length;for (int row = 0; row < inverseHeight; row++) {for (int col = 0; col < inverseWidth; col++) {int pixel = pixelArray[row][col];int r = GImage.getRed(pixel);int g = GImage.getGreen(pixel);int b = GImage.getBlue(pixel);//將像素點的RGB值統一設置為其中的最大值int avg = (Math.max(Math.max(r, b), g) + Math.max(Math.min(r, b), g)) / 2;int newPixel = GImage.createRGBPixel(avg, avg, avg);pixelArray[row][col] = newPixel;}}return new GImage(pixelArray);}/*** 灰度* 灰度處理是通過轉灰度的算法改變像素點的RGB值后進行繪制.*/public GImage gray(GImage source) {int[][] pixelArray = source.getPixelArray();int inverseHeight = pixelArray.length;int inverseWidth = pixelArray[0].length;for (int row = 0; row < inverseHeight; row++) {for (int col = 0; col < inverseWidth; col++) {int pixel = pixelArray[row][col];int r = GImage.getRed(pixel);int g = GImage.getGreen(pixel);int b = GImage.getBlue(pixel);//這里使用的RGB轉灰度算法為Gray = R0.299 + G0.587 + B*0.114int gray = (int) (0.299 * r + 0.587 * g + 0.114 * b);int newPixel = GImage.createRGBPixel(gray, gray, gray);pixelArray[row][col] = newPixel;}}return new GImage(pixelArray);}/*** 利熔爐濾鏡公式實現圖像處理*/public GImage furnace(GImage source) {int[][] pixelArray = source.getPixelArray();int inverseHeight = pixelArray.length;int inverseWidth = pixelArray[0].length;for (int row = 0; row < inverseHeight; row++) {for (int col = 0; col < inverseWidth; col++) {int pixel = pixelArray[row][col];int r = GImage.getRed(pixel);int g = GImage.getGreen(pixel);int b = GImage.getBlue(pixel);int[] rgb = new int[3];rgb[0] = r * 128 / (g + b + 1);rgb[1] = g * 128 / (r + b + 1);rgb[2] = b * 128 / (g + r + 1);int newPixel = GImage.createRGBPixel(rgb[0], rgb[1], rgb[2]);pixelArray[row][col] = newPixel;}}return new GImage(pixelArray);} }總結
以上是生活随笔為你收集整理的初学JAVA项目(三、槑图秀秀)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 管理学论文对人性的假设
- 下一篇: 美国会委员会建议禁止中国国企收购美国资产