Java實現圖像像素化

使用Java實現圖像像素化藝術效果:從方案到實踐的完整指南

在這里插入圖片描述

引言:像素藝術的復興與編程實現

在當今高清、視網膜屏幕的時代,像素藝術(Pixel Art)作為一種復古的數字藝術形式,反而煥發出了新的生命力。從獨立游戲《星露谷物語》到大型游戲《我的世界》,像素風格以其獨特的魅力和懷舊感吸引著大量愛好者。

作為Java開發者,我們能否自己動手,將普通的照片或圖像轉換為這種充滿魅力的像素藝術?答案是肯定的!本文將全程指導您如何使用Java構建一個功能完整、性能優異的圖像像素化應用。我們將從方案設計開始,深入編碼實踐,最后進行嚴格的功能測試,為您呈現一個完整的項目開發流程。

一、方案設計:核心思路與技術選型

在開始編碼之前,一個清晰的方案設計是成功的關鍵。我們需要明確目標、選擇合適的技術棧并設計核心算法。

1.1 項目目標

我們的像素化工具需要實現以下核心功能:

  • 讀取多種常見格式的圖像文件(JPG, PNG, BMP等)
  • 允許用戶調整像素塊大小,控制像素化程度
  • 應用適當的降色算法,模擬有限的調色板效果
  • 支持輸出為多種圖像格式
  • 提供簡單的用戶界面或命令行接口

1.2 技術選型

對于這個項目,我們將使用以下Java技術:

  • Java Swing - 用于構建簡單的圖形用戶界面(可選)
  • BufferedImage類 - Java核心庫中的圖像處理基礎
  • ImageIO類 - 用于圖像的讀取和寫入
  • Java基本數據結構 - 如數組和列表,用于處理像素數據

不使用第三方圖像處理庫(如OpenCV),以展示純Java的實現能力并減少依賴。

1.3 算法設計

像素化的核心算法可以分為兩個主要步驟:

  1. 圖像分割:將原圖像劃分為多個大小相等的像素塊
  2. 顏色平均:對每個像素塊內的所有顏色取平均值,然后用這個平均色填充整個區塊

對于更高級的效果,我們可以加入:

  • 降色處理:將平均顏色映射到有限的預定義調色板
  • 邊緣增強:可選地增強像素塊之間的邊緣,增強像素藝術感

二、開發實踐:一步步實現像素化工具

現在讓我們開始編碼實現。我們將創建一個名為PixelArtGenerator的Java應用。

2.1 項目結構

首先創建以下項目結構:

pixel-art-generator/
│
├── src/
│   └── com/
│       └── example/
│           └── pixelart/
│               ├── PixelArtGenerator.java
│               ├── processor/
│               │   ├── ImagePixelator.java
│               │   └── ColorReducer.java
│               ├── io/
│               │   ├── ImageLoader.java
│               │   └── ImageWriter.java
│               └── ui/
│                   ├── MainFrame.java
│                   └── ImagePanel.java
│
└── resources/├── input/└── output/

2.2 核心像素化算法實現

創建ImagePixelator類,這是應用的核心:

package com.example.pixelart.processor;import java.awt.image.BufferedImage;public class ImagePixelator {/*** 將圖像像素化* @param originalImage 原始圖像* @param pixelSize 像素塊大小(決定像素化程度)* @return 像素化后的圖像*/public BufferedImage pixelate(BufferedImage originalImage, int pixelSize) {int width = originalImage.getWidth();int height = originalImage.getHeight();// 創建新圖像,使用相同的顏色模型BufferedImage pixelatedImage = new BufferedImage(width, height, originalImage.getType());// 遍歷圖像,按像素塊處理for (int y = 0; y < height; y += pixelSize) {for (int x = 0; x < width; x += pixelSize) {// 處理每個像素塊processPixelBlock(originalImage, pixelatedImage, x, y, pixelSize);}}return pixelatedImage;}/*** 處理單個像素塊:計算平均顏色并填充整個區塊*/private void processPixelBlock(BufferedImage src, BufferedImage dest, int startX, int startY, int blockSize) {int width = src.getWidth();int height = src.getHeight();// 確保不超出圖像邊界int blockWidth = Math.min(blockSize, width - startX);int blockHeight = Math.min(blockSize, height - startY);// 計算這個像素塊的平均顏色int avgColor = calculateAverageColor(src, startX, startY, blockWidth, blockHeight);// 用平均顏色填充整個像素塊for (int y = startY; y < startY + blockHeight; y++) {for (int x = startX; x < startX + blockWidth; x++) {dest.setRGB(x, y, avgColor);}}}/*** 計算指定區域內像素的平均顏色*/private int calculateAverageColor(BufferedImage image, int startX, int startY, int width, int height) {long totalRed = 0, totalGreen = 0, totalBlue = 0;int pixelCount = width * height;// 遍歷區域內的所有像素for (int y = startY; y < startY + height; y++) {for (int x = startX; x < startX + width; x++) {int rgb = image.getRGB(x, y);// 提取RGB分量int red = (rgb >> 16) & 0xFF;int green = (rgb >> 8) & 0xFF;int blue = rgb & 0xFF;totalRed += red;totalGreen += green;totalBlue += blue;}}// 計算平均值int avgRed = (int) (totalRed / pixelCount);int avgGreen = (int) (totalGreen / pixelCount);int avgBlue = (int) (totalBlue / pixelCount);// 將RGB分量組合回整數顏色值return (avgRed << 16) | (avgGreen << 8) | avgBlue;}
}

2.3 高級功能:降色處理

為了獲得更接近傳統像素藝術的效果,我們可以添加降色功能:

package com.example.pixelart.processor;import java.awt.Color;
import java.util.Arrays;public class ColorReducer {// 預定義的有限調色板(經典像素藝術顏色)private static final int[] CLASSIC_PALETTE = {0x000000, 0xFFFFFF, 0xFF0000, 0x00FF00, 0x0000FF,0xFFFF00, 0xFF00FF, 0x00FFFF, 0x800000, 0x008000,0x000080, 0x808000, 0x800080, 0x008080, 0x808080,0xC0C0C0, 0xFF8080, 0x80FF80, 0x8080FF, 0xFFFF80};/*** 將顏色減少到有限調色板* @param color 原始顏色* @param palette 使用的調色板* @return 降色后的顏色*/public int reduceColor(int color, int[] palette) {int red = (color >> 16) & 0xFF;int green = (color >> 8) & 0xFF;int blue = color & 0xFF;int closestColor = 0;double minDistance = Double.MAX_VALUE;// 在調色板中尋找最接近的顏色for (int paletteColor : palette) {int pRed = (paletteColor >> 16) & 0xFF;int pGreen = (paletteColor >> 8) & 0xFF;int pBlue = paletteColor & 0xFF;// 計算顏色之間的歐幾里得距離double distance = colorDistance(red, green, blue, pRed, pGreen, pBlue);if (distance < minDistance) {minDistance = distance;closestColor = paletteColor;}}return closestColor;}/*** 計算兩個顏色之間的感知距離*/private double colorDistance(int r1, int g1, int b1, int r2, int g2, int b2) {// 使用更符合人類視覺感知的加權歐幾里得距離double meanRed = (r1 + r2) / 2.0;double deltaRed = r1 - r2;double deltaGreen = g1 - g2;double deltaBlue = b1 - b2;double weightRed = 2 + meanRed / 256;double weightGreen = 4.0;double weightBlue = 2 + (255 - meanRed) / 256;return Math.sqrt(weightRed * deltaRed * deltaRed +weightGreen * deltaGreen * deltaGreen +weightBlue * deltaBlue * deltaBlue);}/*** 獲取經典像素藝術調色板*/public int[] getClassicPalette() {return CLASSIC_PALETTE.clone();}/*** 從圖像中提取自定義調色板(K-means聚類算法)* 這是一個高級功能,可以分析圖像并提取最具代表性的顏色*/public int[] extractPaletteFromImage(BufferedImage image, int paletteSize) {// 實現顏色聚類算法提取調色板// 此處簡化實現,返回一個基本調色板return Arrays.copyOf(CLASSIC_PALETTE, Math.min(paletteSize, CLASSIC_PALETTE.length));}
}

2.4 圖像輸入輸出處理

創建圖像讀寫工具類:

package com.example.pixelart.io;import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;public class ImageLoader {/*** 加載圖像文件*/public BufferedImage loadImage(String filePath) throws IOException {File file = new File(filePath);if (!file.exists()) {throw new IOException("文件不存在: " + filePath);}BufferedImage image = ImageIO.read(file);if (image == null) {throw new IOException("不支持的圖像格式或文件已損壞: " + filePath);}return image;}
}public class ImageWriter {/*** 保存圖像到文件*/public void saveImage(BufferedImage image, String filePath, String format) throws IOException {File outputFile = new File(filePath);boolean success = ImageIO.write(image, format, outputFile);if (!success) {throw new IOException("保存圖像失敗,可能是不支持的格式: " + format);}}/*** 根據文件擴展名自動確定格式*/public void saveImage(BufferedImage image, String filePath) throws IOException {String format = getFormatFromExtension(filePath);saveImage(image, filePath, format);}private String getFormatFromExtension(String filePath) {if (filePath.toLowerCase().endsWith(".png")) return "PNG";if (filePath.toLowerCase().endsWith(".jpg") || filePath.toLowerCase().endsWith(".jpeg")) return "JPEG";if (filePath.toLowerCase().endsWith(".bmp")) return "BMP";if (filePath.toLowerCase().endsWith(".gif")) return "GIF";// 默認使用PNG格式return "PNG";}
}

2.5 主程序與用戶界面

創建一個簡單的主程序來協調各個組件:

package com.example.pixelart;import com.example.pixelart.io.ImageLoader;
import com.example.pixelart.io.ImageWriter;
import com.example.pixelart.processor.ImagePixelator;
import com.example.pixelart.processor.ColorReducer;
import java.awt.image.BufferedImage;
import java.io.IOException;public class PixelArtGenerator {private ImageLoader imageLoader;private ImageWriter imageWriter;private ImagePixelator imagePixelator;private ColorReducer colorReducer;public PixelArtGenerator() {this.imageLoader = new ImageLoader();this.imageWriter = new ImageWriter();this.imagePixelator = new ImagePixelator();this.colorReducer = new ColorReducer();}/*** 生成像素藝術圖像* @param inputPath 輸入圖像路徑* @param outputPath 輸出圖像路徑* @param pixelSize 像素塊大小* @param useColorReduction 是否使用降色處理* @return 處理后的圖像*/public BufferedImage generatePixelArt(String inputPath, String outputPath, int pixelSize, boolean useColorReduction) throws IOException {// 加載原始圖像BufferedImage originalImage = imageLoader.loadImage(inputPath);// 應用像素化BufferedImage pixelatedImage = imagePixelator.pixelate(originalImage, pixelSize);// 可選:應用降色處理if (useColorReduction) {pixelatedImage = applyColorReduction(pixelatedImage);}// 保存結果if (outputPath != null) {imageWriter.saveImage(pixelatedImage, outputPath);}return pixelatedImage;}/*** 應用降色處理到整個圖像*/private BufferedImage applyColorReduction(BufferedImage image) {int width = image.getWidth();int height = image.getHeight();int[] palette = colorReducer.getClassicPalette();BufferedImage reducedImage = new BufferedImage(width, height, image.getType());for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {int rgb = image.getRGB(x, y);int reducedColor = colorReducer.reduceColor(rgb, palette);reducedImage.setRGB(x, y, reducedColor);}}return reducedImage;}/*** 主方法 - 命令行接口*/public static void main(String[] args) {if (args.length < 2) {System.out.println("用法: java PixelArtGenerator <輸入文件> <輸出文件> [像素大小] [是否降色]");System.out.println("示例: java PixelArtGenerator input.jpg output.png 10 true");return;}String inputPath = args[0];String outputPath = args[1];int pixelSize = args.length > 2 ? Integer.parseInt(args[2]) : 10;boolean useColorReduction = args.length > 3 ? Boolean.parseBoolean(args[3]) : false;PixelArtGenerator generator = new PixelArtGenerator();try {long startTime = System.currentTimeMillis();generator.generatePixelArt(inputPath, outputPath, pixelSize, useColorReduction);long endTime = System.currentTimeMillis();System.out.println("像素藝術生成成功!");System.out.println("耗時: " + (endTime - startTime) + "ms");} catch (IOException e) {System.err.println("處理圖像時出錯: " + e.getMessage());e.printStackTrace();}}
}

2.6 圖形用戶界面(可選)

對于希望提供圖形界面的用戶,可以添加一個簡單的Swing界面:

package com.example.pixelart.ui;import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;public class MainFrame extends JFrame {private JLabel imageLabel;private JSpinner pixelSizeSpinner;private JCheckBox colorReductionCheckbox;private JButton processButton;private JButton saveButton;private BufferedImage originalImage;private BufferedImage processedImage;private PixelArtGenerator generator;public MainFrame() {generator = new PixelArtGenerator();initializeUI();}private void initializeUI() {setTitle("Java像素藝術生成器");setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setSize(800, 600);setLayout(new BorderLayout());// 創建控件JPanel controlPanel = new JPanel();pixelSizeSpinner = new JSpinner(new SpinnerNumberModel(10, 1, 50, 1));colorReductionCheckbox = new JCheckBox("使用降色處理");processButton = new JButton("處理圖像");saveButton = new JButton("保存結果");controlPanel.add(new JLabel("像素大小:"));controlPanel.add(pixelSizeSpinner);controlPanel.add(colorReductionCheckbox);controlPanel.add(processButton);controlPanel.add(saveButton);// 圖像顯示區域imageLabel = new JLabel("請選擇圖像文件", SwingConstants.CENTER);imageLabel.setHorizontalAlignment(SwingConstants.CENTER);JScrollPane scrollPane = new JScrollPane(imageLabel);add(controlPanel, BorderLayout.NORTH);add(scrollPane, BorderLayout.CENTER);// 添加事件監聽器processButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {processImage();}});saveButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {saveImage();}});// 添加菜單JMenuBar menuBar = new JMenuBar();JMenu fileMenu = new JMenu("文件");JMenuItem openItem = new JMenuItem("打開");openItem.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {openImage();}});fileMenu.add(openItem);menuBar.add(fileMenu);setJMenuBar(menuBar);}private void openImage() {JFileChooser fileChooser = new JFileChooser();int result = fileChooser.showOpenDialog(this);if (result == JFileChooser.APPROVE_OPTION) {File selectedFile = fileChooser.getSelectedFile();try {originalImage = new ImageLoader().loadImage(selectedFile.getAbsolutePath());displayImage(originalImage);} catch (Exception ex) {JOptionPane.showMessageDialog(this, "無法加載圖像: " + ex.getMessage(),"錯誤", JOptionPane.ERROR_MESSAGE);}}}private void processImage() {if (originalImage == null) {JOptionPane.showMessageDialog(this, "請先打開一個圖像文件");return;}int pixelSize = (Integer) pixelSizeSpinner.getValue();boolean useColorReduction = colorReductionCheckbox.isSelected();try {processedImage = generator.generatePixelArt(null, pixelSize, useColorReduction);displayImage(processedImage);} catch (Exception ex) {JOptionPane.showMessageDialog(this, "處理圖像時出錯: " + ex.getMessage(),"錯誤", JOptionPane.ERROR_MESSAGE);}}private void saveImage() {if (processedImage == null) {JOptionPane.showMessageDialog(this, "沒有處理后的圖像可保存");return;}JFileChooser fileChooser = new JFileChooser();int result = fileChooser.showSaveDialog(this);if (result == JFileChooser.APPROVE_OPTION) {File selectedFile = fileChooser.getSelectedFile();try {new ImageWriter().saveImage(processedImage, selectedFile.getAbsolutePath());JOptionPane.showMessageDialog(this, "圖像保存成功!");} catch (Exception ex) {JOptionPane.showMessageDialog(this, "保存圖像時出錯: " + ex.getMessage(),"錯誤", JOptionPane.ERROR_MESSAGE);}}}private void displayImage(BufferedImage image) {ImageIcon icon = new ImageIcon(image);imageLabel.setIcon(icon);imageLabel.setText("");}public static void main(String[] args) {SwingUtilities.invokeLater(new Runnable() {@Overridepublic void run() {new MainFrame().setVisible(true);}});}
}

三、測試與驗證:確保應用質量

任何完整的項目都需要經過充分的測試。我們將從單元測試和功能測試兩個方面來驗證我們的像素化工具。

3.1 單元測試

使用JUnit框架編寫單元測試:

import org.junit.Test;
import static org.junit.Assert.*;
import java.awt.image.BufferedImage;public class ImagePixelatorTest {@Testpublic void testCalculateAverageColor() {// 創建一個2x2的測試圖像BufferedImage testImage = new BufferedImage(2, 2, BufferedImage.TYPE_INT_RGB);// 設置四個像素的顏色:紅、綠、藍、白testImage.setRGB(0, 0, 0xFF0000); // 紅色testImage.setRGB(1, 0, 0x00FF00); // 綠色testImage.setRGB(0, 1, 0x0000FF); // 藍色testImage.setRGB(1, 1, 0xFFFFFF); // 白色ImagePixelator pixelator = new ImagePixelator();// 計算平均顏色應該是灰色 (0x7F7F7F)int avgColor = pixelator.calculateAverageColor(testImage, 0, 0, 2, 2);// 提取RGB分量int red = (avgColor >> 16) & 0xFF;int green = (avgColor >> 8) & 0xFF;int blue = avgColor & 0xFF;// 每個分量應該在127-128左右assertTrue("紅色分量應該在120-135范圍內", red >= 120 && red <= 135);assertTrue("綠色分量應該在120-135范圍內", green >= 120 && green <= 135);assertTrue("藍色分量應該在120-135范圍內", blue >= 120 && blue <= 135);}@Testpublic void testPixelateWithSmallImage() {// 創建一個小圖像測試基本像素化功能BufferedImage smallImage = new BufferedImage(4, 4, BufferedImage.TYPE_INT_RGB);// 填充測試圖案for (int y = 0; y < 4; y++) {for (int x = 0; x < 4; x++) {if ((x + y) % 2 == 0) {smallImage.setRGB(x, y, 0xFF0000); // 紅色} else {smallImage.setRGB(x, y, 0x0000FF); // 藍色}}}ImagePixelator pixelator = new ImagePixelator();BufferedImage result = pixelator.pixelate(smallImage, 2);// 使用2x2像素塊,結果應該只有4個像素塊// 檢查左上角像素塊的顏色int topLeftColor = result.getRGB(0, 0);int topRightColor = result.getRGB(2, 0);// 左上角像素塊應該是一個平均色(紅藍混合)int topLeftRed = (topLeftColor >> 16) & 0xFF;assertTrue("左上角像素塊紅色分量應該在120-135范圍內", topLeftRed >= 120 && topLeftRed <= 135);// 所有2x2塊內的像素應該顏色一致for (int y = 0; y < 2; y++) {for (int x = 0; x < 2; x++) {assertEquals("塊內像素顏色應該一致", topLeftColor, result.getRGB(x, y));}}}
}public class ColorReducerTest {@Testpublic void testReduceColorToPalette() {ColorReducer reducer = new ColorReducer();int[] palette = {0xFF0000, 0x00FF00, 0x0000FF}; // 只有紅、綠、藍// 測試顏色應該映射到最接近的調色板顏色assertEquals("粉紅色應該映射到紅色", 0xFF0000, reducer.reduceColor(0xFF8080, palette));assertEquals("黃綠色應該映射到綠色", 0x00FF00, reducer.reduceColor(0x80FF80, palette));assertEquals("淡藍色應該映射到藍色", 0x0000FF, reducer.reduceColor(0x8080FF, palette));}
}

3.2 功能測試

創建功能測試類來驗證整個應用的工作流程:

import org.junit.Test;
import java.io.File;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;public class FunctionalTest {@Testpublic void testCompleteWorkflow() {try {// 創建一個簡單的測試圖像BufferedImage testImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);// 填充漸變背景for (int y = 0; y < 100; y++) {for (int x = 0; x < 100; x++) {int color = (x * 255 / 100) << 16 | (y * 255 / 100) << 8;testImage.setRGB(x, y, color);}}// 保存測試圖像File inputFile = new File("test_input.jpg");ImageIO.write(testImage, "JPEG", inputFile);// 使用我們的應用處理圖像PixelArtGenerator generator = new PixelArtGenerator();BufferedImage result = generator.generatePixelArt("test_input.jpg", "test_output.png", 10, true);// 驗證結果assertNotNull("結果圖像不應為null", result);assertEquals("寬度應該相同", testImage.getWidth(), result.getWidth());assertEquals("高度應該相同", testImage.getHeight(), result.getHeight());// 檢查是否確實進行了像素化// 相鄰像素在像素塊內應該顏色相同,在不同塊可能不同int color1 = result.getRGB(0, 0);int color2 = result.getRGB(5, 5); // 同一像素塊內int color3 = result.getRGB(15, 15); // 不同像素塊assertEquals("同一像素塊內的顏色應該相同", color1, color2);// 清理測試文件inputFile.delete();new File("test_output.png").delete();} catch (Exception e) {fail("功能測試失敗: " + e.getMessage());}}
}

3.3 性能測試與優化

對于大型圖像,性能可能成為問題。我們可以添加性能測試并考慮優化:

public class PerformanceTest {@Testpublic void testPerformanceWithLargeImage() {// 創建一個大圖像測試性能BufferedImage largeImage = new BufferedImage(2000, 2000, BufferedImage.TYPE_INT_RGB);ImagePixelator pixelator = new ImagePixelator();long startTime = System.currentTimeMillis();BufferedImage result = pixelator.pixelate(largeImage, 10);long endTime = System.currentTimeMillis();long duration = endTime - startTime;System.out.println("處理2000x2000圖像耗時: " + duration + "ms");// 對于實際應用,這個時間應該可以接受// 如果太慢,可以考慮以下優化:// 1. 使用多線程處理不同的圖像區域// 2. 使用更高效的顏色計算算法// 3. 對于極大圖像,可以考慮分塊處理并保存assertTrue("處理時間應在合理范圍內", duration < 10000); // 10秒內}
}

四、進一步改進與擴展思路

我們的基本實現已經完成,但還有很多可以改進和擴展的方向:

4.1 性能優化

  1. 多線程處理:將圖像分割成多個區域,使用多線程并行處理
  2. 內存優化:對于極大圖像,使用分塊處理策略避免內存溢出
  3. 算法優化:使用更高效的平均顏色計算方法和顏色距離算法

4.2 功能擴展

  1. 更多像素藝術效果:添加抖動(dithering)算法模擬更多顏色
  2. 邊緣檢測與增強:在像素塊之間添加深色線條增強像素感
  3. 動畫支持:擴展支持GIF動畫的像素化
  4. 批量處理:支持批量處理多個圖像文件
  5. 預設風格:提供多種像素藝術風格預設(游戲boy風格、NES風格等)

4.3 用戶體驗改進

  1. 實時預覽:在處理前提供實時預覽效果
  2. 歷史記錄:保存用戶的操作歷史和參數設置
  3. 撤銷/重做:支持多次操作的撤銷和重做
  4. 社交媒體分享:集成社交媒體分享功能

在這里插入圖片描述

結語

通過本文,我們完整地實現了一個使用Java將圖像轉換為像素藝術的應用。從方案設計、核心算法實現到測試驗證,我們涵蓋了開發一個完整項目的所有關鍵環節。

這個項目不僅具有實際應用價值,還能幫助開發者深入理解Java圖像處理、顏色計算和算法優化等多個重要概念。您可以根據實際需求進一步擴展和優化這個應用,甚至可以將其發展為一個小型的商業或開源項目。

希望本文對您的Java編程之旅有所啟發和幫助!如果您有任何問題或建議,歡迎留言討論。


版權聲明:本文為原創文章,轉載請注明出處。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/920920.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/920920.shtml
英文地址,請注明出處:http://en.pswp.cn/news/920920.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SpringBoot 自研運行時 SQL 調用樹,3 分鐘定位慢 SQL!

在復雜的業務系統中&#xff0c;一個接口往往會執行多條SQL&#xff0c;如何直觀地看到這些SQL的調用關系和執行情況&#xff1f; 本文將使用SpringBoot MyBatis攔截器構建一個SQL調用樹可視化系統。 項目背景 在日常開發中&#xff0c;我們經常遇到這樣的場景&#xff1a; …

部署 Go 項目的 N 種方法

Go 語言&#xff08;Golang&#xff09;以其簡單、高效和易于部署的特點&#xff0c;成為了很多企業開發和部署服務的首選語言。無論是微服務架構&#xff0c;還是命令行工具&#xff0c;Go 的編譯方式和標準庫使得部署變得更加輕松。本文將介紹部署 Go 語言項目的幾種常見方法…

【ARM】MDK工程切換高版本的編譯器后出現error: A1167E\A1159E\A1137E\A1517E\A1150E報錯

1、 文檔目標解決工程從Compiler 5切換到Compiler 6進行編譯時出現一些非語法問題上的報錯。2、 問題場景對于一些使用Compiler 5進行編譯的工程&#xff0c;要切換到Compiler 6進行編譯的時候&#xff0c;原本無任何報錯警告信息的工程在使用Compiler 6進行編譯后出現了一些非…

AtCoder Beginner Contest 421

文章目錄A MisdeliveryB Fibonacci ReversedC AlternatedD RLE MovingE YachtF Erase between X and YG Increase to make it IncreasingAtCoder Beginner Contest 421A Misdelivery Mansion AtCoder has N rooms numbered from room 1 to room N. Each room i is inhabited b…

數據結構:冒泡排序 (Bubble Sort)

目錄 從最簡單的操作開始 如何利用這個原子操作實現一個具體的小目標&#xff1f; 我們來手動模擬一下&#xff1a; 如何從一個小目標擴展到最終目標&#xff1f; 代碼的逐步完善 第一階段&#xff1a;定義函數框架和我們需要的“原子操作” 第二階段&#xff1a;實現“…

教育項目管理工具新趨勢:可視化與自動化如何提升效率?

課程項目不同于普通商業項目&#xff0c;它涉及 “教研設計→內容開發→師資準備→市場推廣→學員服務” 全鏈路&#xff0c;環節多、角色雜、周期跨度大。傳統的 Excel 表格、口頭溝通不僅難以追蹤進度&#xff0c;更易造成信息斷層。而看板工具憑借 “可視化流程、輕量化協作…

計算兩個二值圖像的交集計算交點數量的基礎上,進一步使用 DBSCAN 算法對交點進行聚

好的&#xff0c;如果你需要在計算交點數量的基礎上&#xff0c;進一步使用 DBSCAN 算法對交點進行聚類&#xff0c;以合并距離較近的點&#xff0c;可以按照以下步驟實現&#xff1a; 計算交點&#xff1a;使用 cv2.bitwise_and 計算兩個二值圖像的交集&#xff0c;并提取交點…

Linux中的IP命令詳解

華子目錄 1.ip命令是什么1.1ip命令的由來1.2ip命令的安裝包1.2ip選項&#xff08;基本不用&#xff09; 2.查看網絡信息2.1顯示全部網絡接口信息2.2顯示單個網絡接口信息2.3顯示單個接口狀態2.4查看路由表2.5查看arp緩存 3.設置網卡ip地址3.1啟用或停用網卡3.2設置默認網關3.3新…

如何解決pip安裝報錯ModuleNotFoundError: No module named ‘tox’問題

【Python系列Bug修復PyCharm控制臺pip install報錯】如何解決pip安裝報錯ModuleNotFoundError: No module named ‘tox’問題 摘要 在使用 PyCharm 2025 控制臺執行 pip install 命令時&#xff0c;開發者經常會遇到如下錯誤&#xff1a; ModuleNotFoundError: No module nam…

拆分TypeScript項目的學習收獲:處理編譯緩存和包緩存,引用本地項目,使用相對路徑

最近需要將工作中的一個TS包拆出一部分代碼&#xff0c;以便在多個團隊和項目中共享。原以為這會是一項特別簡單的工作&#xff0c;但是也花了兩天才大致拆成功。因此記錄一下&#xff0c;也給有類似需求的同學一點經驗。 所拆項目的大致功能&#xff1a;整個項目的結構大致分為…

瑞芯微RK3576平臺FFmpeg硬件編解碼移植及性能測試實戰攻略

本文介紹瑞芯微RK3576平臺&#xff0c;FFmpeg硬件編解碼移植及性能測試方法。 FFmpeg簡介與實測數據 FFmpeg簡介 FFmpeg是一套多媒體框架&#xff0c;能夠解碼、編碼、轉碼、復用、解復用、流、過濾和播放數字音頻、視頻&#xff0c;提供了錄制、轉換以及流化音視頻的完整解…

【網絡安全入門基礎教程】網絡安全零基礎學習方向及需要掌握的技能

最近總有同學問我&#xff0c;0基礎怎么學網絡安全&#xff1f;0基礎可以轉行做網絡安全嗎&#xff1f;網絡安全有哪些學習方向&#xff1f;每個方向需要掌握哪些技能&#xff1f;今天給大家簡單寫一下。 我的回答是先了解&#xff0c;再入行。 具體怎么做呢&#xff1f; 首…

Altium Designer中的Net-Tie:解決多網絡合并與電氣隔離的利器

Altium Designer中的Net-Tie:解決多網絡合并與電氣隔離的利器 在復雜的PCB設計中,我們常常會遇到一些特殊的電氣連接需求。例如,需要將兩個或多個邏輯上獨立但物理上需要連接的網絡(如不同電源域的GND)在特定點進行連接(單點連接),同時又要保持其網絡標識的獨立性。 …

計算機畢設項目 基于Python與機器學習的B站視頻熱度分析與預測系統 基于隨機森林算法的B站視頻內容熱度預測系統

&#x1f495;&#x1f495;作者&#xff1a;計算機源碼社 &#x1f495;&#x1f495;個人簡介&#xff1a;本人八年開發經驗&#xff0c;擅長Java、Python、PHP、.NET、Node.js、Spark、hadoop、Android、微信小程序、爬蟲、大數據、機器學習等&#xff0c;大家有這一塊的問題…

百勝軟件×OceanBase深度合作,賦能品牌零售數字化實踐降本增效

8月28日&#xff0c;由OceanBase主辦的“2025零售數據底座創新大會”在上海舉行。大會重磅發布了由愛分析、OceanBase攜手王歆、沈剛兩位行業專家聯合編制的《零售一體化云數據庫白皮書》。白皮書系統梳理了從“大促流量應對”到“AI應用落地”的全流程方法論&#xff0c;并為不…

2025年Java在中國開發語言排名分析報告

引言 在軟件定義世界的2025年&#xff0c;編程語言的戰略價值已超越工具屬性&#xff0c;成為產業數字化轉型的核心支撐與開發者思維模式的延伸載體。TIOBE指數作為全球技術市場變化的重要晴雨表&#xff0c;通過追蹤工程師分布、課程設置、供應商動態及搜索引擎數據&#xff0…

TDengine 日期時間函數 DAYOFWEEK 使用手冊

DAYOFWEEK 函數使用手冊 函數描述 DAYOFWEEK 函數用于返回指定日期是一周中的第幾天。該函數遵循標準的星期編號約定&#xff0c;返回值范圍為 1-7&#xff0c;其中&#xff1a; 1 星期日 (Sunday)2 星期一 (Monday)3 星期二 (Tuesday)4 星期三 (Wednesday)5 星期四 (T…

從RNN到BERT

目錄 序列模型簡介RNN循環神經網絡LSTM長短期記憶網絡Transformer架構BERT模型詳解實踐項目 序列模型簡介 什么是序列數據&#xff1f; 序列數據是按照特定順序排列的數據&#xff0c;其中元素的順序包含重要信息。常見的序列數據包括&#xff1a; 文本&#xff1a;單詞或字…

橢圓曲線的數學基礎

一、引言 橢圓曲線密碼學&#xff08;Elliptic Curve Cryptography, ECC&#xff09;是現代公鑰密碼學的核心工具之一。 相比傳統的 RSA&#xff0c;ECC 可以用 更短的密鑰長度 提供 同等甚至更高的安全性&#xff0c;因此被廣泛應用于區塊鏈、TLS、移動設備加密等場景。 要理解…

從能耗黑洞到精準智控:ASCB2智慧空開重構高校宿舍用電能效模型

隨著智慧校園建設不斷推進&#xff0c;校園宿舍的用電管理面臨著安全性、智能化與可視化的多重挑戰。傳統用電監控手段在數據采集、實時控制和故障響應方面存在明顯不足。安科瑞ASCB2系列物聯網斷路器通過集成多種智能感知、保護控制與通信手段&#xff0c;為高校宿舍提供了一種…