使用Java OpenCV旋转图像时像素颜色异常变化问题求助
问题解决:OpenCV旋转图像后颜色失真
核心问题原因
- 重复JPG有损压缩:当前代码在
BufferedImage和Mat转换时,反复使用JPG格式编码解码。JPG是有损压缩格式,每一次转换都会丢失像素细节,多次旋转后颜色失真会越来越严重。 - 颜色空间不匹配:OpenCV默认使用BGR颜色通道顺序,而JavaFX/Swing的
BufferedImage采用RGB顺序,直接转换会导致颜色反转(比如蓝色变红色)。
修正后的代码
替换原有转换方法并调整旋转逻辑,避免有损压缩并修正颜色空间:
package application; import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.io.IOException; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.imgproc.Imgproc; import javafx.embed.swing.SwingFXUtils; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.image.Image; import javafx.scene.image.ImageView; public class SampleController { @FXML private ImageView myimageview; @FXML private Button showimageButton, rotateButton; @FXML void rotateButtonClicked(ActionEvent event) throws Exception { BufferedImage image = SwingFXUtils.fromFXImage(myimageview.getImage(), null); Mat src = BufferedImage2Mat(image); // 将RGB转为OpenCV默认的BGR颜色空间 Imgproc.cvtColor(src, src, Imgproc.COLOR_RGB2BGR); Core.rotate(src, src, Core.ROTATE_90_CLOCKWISE); // 转换回RGB颜色空间适配JavaFX显示 Imgproc.cvtColor(src, src, Imgproc.COLOR_BGR2RGB); image = Mat2BufferedImage(src); try { Image converted_image = SwingFXUtils.toFXImage(image, null); myimageview.setImage(converted_image); } catch (Exception e) { System.out.println(e); } } // 直接通过像素数组转换BufferedImage到Mat,避免JPG编码 public Mat BufferedImage2Mat(BufferedImage image) { Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3); byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); mat.put(0, 0, data); return mat; } // 直接通过像素数组转换Mat到BufferedImage,避免JPG解码 static BufferedImage Mat2BufferedImage(Mat matrix) { int type = BufferedImage.TYPE_3BYTE_BGR; // 处理灰度图像的情况 if (matrix.channels() == 1) { type = BufferedImage.TYPE_BYTE_GRAY; } byte[] buffer = new byte[matrix.channels() * matrix.cols() * matrix.rows()]; matrix.get(0, 0, buffer); BufferedImage image = new BufferedImage(matrix.cols(), matrix.rows(), type); final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); System.arraycopy(buffer, 0, targetPixels, 0, buffer.length); return image; } @FXML void showimageButtonClicked(ActionEvent event) { Image im = new Image("file:///C:\\Users\\poste\\eclipse-workspace\\dragImage\\Images\\temp.jpg"); myimageview.setImage(im); } }
关键修改说明
- 移除JPG编码解码步骤:新的转换方法直接操作底层像素数组,完全避免了有损压缩带来的颜色损失。
- 颜色空间适配:在旋转前后添加
Imgproc.cvtColor转换,让OpenCV处理BGR格式,转换回RGB后再给JavaFX显示,解决颜色反转问题。 - 支持灰度图像:转换方法中增加了灰度图像的判断,兼容单通道图像的转换。
内容的提问来源于stack exchange,提问作者Mouad_thf
相关产品推荐
相关产品推荐

