【发布时间】:2017-04-28 07:42:36
【问题描述】:
我正在尝试使用 OpenCV 3.1 Java 操作单个图像像素。 OpenCV 将图像读取为字节数组。我想将彩色图像转换为灰度图像,而不用函数 Y = R*0.299 + G*0.587 + B*0.114 改变图像通道的总数,因此结果仍然是 RGB 图像(3 个颜色通道)。根据我的理解,因为 0.299 + 0.587 + 0.114 = 1 的和,虽然字节范围从 -128 到 127,但在转换为字节时应该没有下溢或上溢的问题。但是结果很奇怪,因为图像的一些白色区域变成了黑色,而一些黑色区域变成了白色。我假设发生了下溢或溢出。这是我的代码:
List<Mat> channels = new ArrayList<>();
Core.split(intImage, channels);
int totalInt = (int)(channels.get(0).total());
byte[] blue = new byte[totalInt];
byte[] green = new byte[totalInt];
byte[] red = new byte[totalInt];
channels.get(0).get(0, 0, blue);
channels.get(1).get(0, 0, green);
channels.get(2).get(0, 0, red);
for (int i = 0; i < totalInt; i++) {
byte s = (byte)(blue[i]*0.114 + green[i]*0.587 + red[i]*0.299);
blue[i] = red[i] = green[i] = s;
}
channels.get(0).put(0, 0, blue);
channels.get(1).put(0, 0, green);
channels.get(2).put(0, 0, red);
Mat gray = new Mat();
Core.merge(channels, gray);
我尝试将图像转换为CvType.CV_16S,它代表无符号短,到目前为止它没有问题。转换为 CV_8UC3 仍然是字节。我担心堆问题,因为当我尝试使用 CV_32S 的 int 时,一些大图像会发生堆错误。所以这是我的问题:
- 如果可以,我该如何防止或处理这些上溢/下溢。我仍在考虑使用字节,因为它会减少堆/内存的使用。
- 如果第一个是唯一的选项,我如何才能将 CV_16S 直接转换为 BufferedImage 而无需转换回原始的 Mat 类型,因为我正在使用 Swing 显示图像。
我找到了从Mat转换为BufferedImage的方法如下:
public BufferedImage toBufferedImage(Mat matrix) {
int type = BufferedImage.TYPE_BYTE_GRAY;
if (matrix.channels() > 1) {
type = BufferedImage.TYPE_3BYTE_BGR;
}
BufferedImage image = new BufferedImage(matrix.cols(),
matrix.rows(), type);
final byte[] targetPixels =
((DataBufferByte)image.getRaster().getDataBuffer()).getData();
matrix.get(0, 0, targetPixels);
return image;
}
请解释一下,字节转换发生了什么。
【问题讨论】: