BufferedImage由Gray转成RGB,颜色不变

本文提供了一个Java示例代码片段,展示了如何将灰度图像转换为RGB图像。通过创建BufferedImage对象并使用Graphics2D类进行绘制,实现了图像颜色空间的转换,此过程保留了原始图像的灰度特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

		BufferedImage biGray = new BufferedImage(512,512,BufferedImage.TYPE_BYTE_GRAY);
		BufferedImage biRGB = new BufferedImage(biGray.getWidth(), biGray.getHeight(),BufferedImage.TYPE_INT_RGB);
		//颜色变了
//		ColorConvertOp cco = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB), null);
//		cco.filter(biGray, biRGB);
		//颜色不变
		Graphics2D g = biRGB.createGraphics();
		g.drawImage(biGray, 0, 0, null);
		g.dispose();

 

<audio controls="controls" style="display: none;"></audio>

java.lang.IllegalArgumentException: Rescaling cannot be performed on an indexed image at java.desktop/java.awt.image.RescaleOp.filter(RescaleOp.java:371) private BufferedImage preprocessImage(BufferedImage image) { // 转换索引图像为RGB格式 image = convertToRGB(image); // 1. 增强对比度 RescaleOp rescaleOp = new RescaleOp(1.2f, 0, null); BufferedImage enhanced = rescaleOp.filter(image, null); // 2. 转换为灰度BufferedImage gray = new BufferedImage( enhanced.getWidth(), enhanced.getHeight(), BufferedImage.TYPE_BYTE_GRAY ); Graphics gGray = gray.getGraphics(); gGray.drawImage(enhanced, 0, 0, null); gGray.dispose(); // 3. 简化版自适应二值化(高性能) BufferedImage binary = new BufferedImage( gray.getWidth(), gray.getHeight(), BufferedImage.TYPE_BYTE_BINARY ); int avgBrightness = 0; for (int y = 0; y < gray.getHeight(); y += 5) { for (int x = 0; x < gray.getWidth(); x += 5) { int rgb = gray.getRGB(x, y); avgBrightness += (rgb >> 16) & 0xFF; } } avgBrightness = avgBrightness / ((gray.getWidth()/5) * (gray.getHeight()/5)); int threshold = avgBrightness - 15; for (int y = 0; y < gray.getHeight(); y++) { for (int x = 0; x < gray.getWidth(); x++) { int rgb = gray.getRGB(x, y); int r = (rgb >> 16) & 0xFF; int newRgb = (r > threshold) ? 0xFFFFFF : 0x000000; binary.setRGB(x, y, newRgb); } } // 4. 字符分离优化(腐蚀操作) float[] kernel = {0, 1, 0, 1, 1, 1, 0, 1, 0}; ConvolveOp erodeOp = new ConvolveOp(new Kernel(3, 3, kernel)); return erodeOp.filter(binary, null); } private BufferedImage convertToRGB(BufferedImage src) { if (src.getType() == BufferedImage.TYPE_BYTE_INDEXED) { BufferedImage newImage = new BufferedImage( src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_RGB ); Graphics2D g = newImage.createGraphics(); g.drawImage(src, 0, 0, null); g.dispose(); return newImage; } return src; }
07-25
// 图像预处理方法 private BufferedImage preprocessImage(BufferedImage original) { try { // 转换为OpenCV Mat格式 Mat mat = bufferedImageToMat(original); // 灰度化 Mat gray = new Mat(); Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY); // 二值化(Otsu自动阈值) Mat binary = new Mat(); Imgproc.threshold(gray, binary, 0, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU); // 形态学操作:分离粘连字符(垂直膨胀) Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(1, 2)); Imgproc.dilate(binary, binary, kernel); // 转换回BufferedImage return matToBufferedImage(binary); } catch (Exception e) { e.printStackTrace(); return original; // 出错时返回原图 } } // BufferedImage转OpenCV Mat private Mat bufferedImageToMat(BufferedImage image) { byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3); mat.put(0, 0, data); return mat; } // OpenCV Mat转BufferedImage private BufferedImage matToBufferedImage(Mat mat) { int type = BufferedImage.TYPE_BYTE_GRAY; if (mat.channels() > 1) { type = BufferedImage.TYPE_3BYTE_BGR; } byte[] data = new byte[mat.cols() * mat.rows() * (int)mat.elemSize()]; mat.get(0, 0, data); BufferedImage image = new BufferedImage(mat.cols(), mat.rows(), type); image.getRaster().setDataElements(0, 0, mat.cols(), mat.rows(), data); return image; } @PostConstruct public void initOcrEngine() { tesseract = new Tesseract(); //语言包路径和支持语言 tesseract.setDatapath(tessDataPath); tesseract.setLanguage("eng+chi_sim"); tesseract.setPageSegMode(4); // 单行识别模式 tesseract.setOcrEngineMode(2); //LSTM引擎 tesseract.setTessVariable("preserve_interword_spaces", "1"); } /** * OCR识别图片内容 */ private String extractImageText(MultipartFile file) { try (InputStream is = file.getInputStream()) { BufferedImage image = ImageIO.read(is); if (image == null) { return MessageUtils.message("Image.parsing.failed"); } BufferedImage processedImage = preprocessImage(image); String result = tesseract.doOCR(processedImage); //OCR识别 result = postProcess(result); result = result.replaceAll("\\s+", " ").trim(); System.out.println("图片内容:\n" + result); return result; } catch (Exception e) { e.printStackTrace(); return MessageUtils.message("file.read.picture.error"); } }我的方法java.lang.UnsupportedOperationException: Provided data element number (1049024) should be multiple of the Mat channels count (3)
07-26
/** * ocr配置 / @PostConstruct public void initOcrEngine() { tesseract = new Tesseract(); //语言包路径和支持语言 tesseract.setDatapath(tessDataPath); tesseract.setLanguage(“eng+chi_sim”); tesseract.setPageSegMode(6); //自动页面分割 tesseract.setOcrEngineMode(3); //LSTM引擎 } /* * OCR识别图片内容 */ private String extractImageText(MultipartFile file) { try (InputStream is = file.getInputStream()) { BufferedImage image = ImageIO.read(is); if (image == null) { return MessageUtils.message(“Image.parsing.failed”); } // image = increaseVerticalSpacingBetweenText(image, 50); // image = increaseHorizontalSpacing(image, 20); // image=fixCharacterSticking(image); saveDebugImage(image, “3_final.png”); String result = tesseract.doOCR(image); //OCR识别 result = postProcess(result); result = result.replaceAll(“\s+”, " ").trim(); System.out.println(“图片内容:\n” + result); return result; } catch (Exception e) { e.printStackTrace(); return MessageUtils.message(“file.read.picture.error”); } } private void saveDebugImage(BufferedImage img, String filename) throws IOException { // 保存到项目目录下的debug文件夹 String basePath = “D:/pdf/debug/”; File outputDir = new File(basePath); if (!outputDir.exists()) outputDir.mkdirs(); String fullPath = basePath + filename; ImageIO.write(img, “png”, new File(fullPath)); } public BufferedImage fixCharacterSticking(BufferedImage original) { // 1. 灰度化处理 BufferedImage grayscale = toGrayscale(original); // 2. 自适应二值化(无OpenCV) BufferedImage binary = adaptiveBinarization(grayscale); // 3. 文本行检测与分割 List<int[]> textLines = detectTextLines(binary); // 4. 垂直间距增强 return addVerticalSpacing(binary, textLines, 15); } // 灰度化处理 private BufferedImage toGrayscale(BufferedImage src) { BufferedImage gray = new BufferedImage( src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_GRAY); Graphics g = gray.getGraphics(); g.drawImage(src, 0, 0, null); g.dispose(); return gray; } // 自适应二值化(无OpenCV) private BufferedImage adaptiveBinarization(BufferedImage gray) { int width = gray.getWidth(); int height = gray.getHeight(); BufferedImage binary = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY); // 使用局部阈值(7x7窗口) int windowSize = 7; int halfWindow = windowSize / 2; for (int y = halfWindow; y < height - halfWindow; y++) { for (int x = halfWindow; x < width - halfWindow; x++) { // 计算局部区域平均灰度 int sum = 0; for (int j = -halfWindow; j <= halfWindow; j++) { for (int i = -halfWindow; i <= halfWindow; i++) { Color pixel = new Color(gray.getRGB(x + i, y + j)); sum += pixel.getRed(); // 灰度图R=G=B } } int avg = sum / (windowSize * windowSize); // 应用阈值(带偏移量) Color current = new Color(gray.getRGB(x, y)); int threshold = Math.max(10, avg - 15); // 动态阈值 int newPixel = (current.getRed() < threshold) ? 0 : 0xFFFFFF; binary.setRGB(x, y, newPixel); } } return binary; } // 文本行检测 private List<int[]> detectTextLines(BufferedImage binary) { List<int[]> lines = new ArrayList<>(); int height = binary.getHeight(); int width = binary.getWidth(); boolean inTextLine = false; int lineStart = 0; for (int y = 0; y < height; y++) { int blackCount = 0; for (int x = 0; x < width; x++) { if ((binary.getRGB(x, y) & 0xFFFFFF) == 0) { blackCount++; } } // 检测文本行(黑色像素超过5%) if (blackCount > width * 0.05) { if (!inTextLine) { lineStart = y; inTextLine = true; } } else { if (inTextLine) { lines.add(new int[]{lineStart, y - 1}); inTextLine = false; } } } // 处理最后一行 if (inTextLine) { lines.add(new int[]{lineStart, height - 1}); } return lines; } // 添加垂直间距 private BufferedImage addVerticalSpacing( BufferedImage src, List<int[]> lines, int spacing) { int width = src.getWidth(); int newHeight = src.getHeight() + (lines.size() - 1) * spacing; BufferedImage result = new BufferedImage(width, newHeight, BufferedImage.TYPE_BYTE_BINARY); // 填充白色背景 Graphics2D g = result.createGraphics(); g.setColor(Color.WHITE); g.fillRect(0, 0, width, newHeight); // 复制文本行并添加间距 int currentY = 0; for (int[] line : lines) { int lineHeight = line[1] - line[0] + 1; g.drawImage(src.getSubimage(0, line[0], width, lineHeight), 0, currentY, null); currentY += lineHeight + spacing; } g.dispose(); return result; } 你给我的代码 有上下字符有空隙了 然后也把我的字符给切成两半了
07-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值