65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 OpenCV 在 Android 中实现夜视摄像头

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2016年10月1日

CPOL
viewsIcon

18020

在 Android 中使用 OpenCV 实现夜视。

引言

软件夜视通常通过直方图均衡化伽马校正来实现,而这两种方法都已在 OpenCV 中得到支持。对于任何 Android 设备,我们可以使用 OpenCV4Android 来处理设备捕获的图像。

背景

这段代码是在我开发 myMobKit 时编写的。你可以在 这里 找到源代码。

使用代码

在 Android 编程中,在相机预览期间,你将获得一个字节数组,它是一个 YUV420sp 图像。

使用 OpenCV,将图像转换为灰度图像,并使用 OpenCV API 对图像应用直方图均衡化。

@Override
public byte[] process(final byte[] source) {
    try {
        if (source == null) return null;
        if (sourceFrame == null) {
            if (!isColor) {
                this.sourceFrame = new Mat(height + (height / 2), width, CvType.CV_8UC1);
                this.processedFrame = new Mat(height + (height / 2), width, CvType.CV_8UC1);
            } else {
                this.sourceFrame = new Mat(height + (height / 2), width, CvType.CV_8UC1);
                this.processedFrame = new Mat(height + (height / 2), width, CvType.CV_8UC3);
                this.ycrcb = new Mat();
            }
        }
        sourceFrame.put(0, 0, source);

        // convert sourceFrame to gray scale
        if (!isColor) {
            Imgproc.cvtColor(sourceFrame, processedFrame, Imgproc.COLOR_YUV420p2GRAY);

            // Apply Histogram Equalization
            Imgproc.equalizeHist(processedFrame, processedFrame);

            // Convert to JPEG
            return CvUtils.grayToJpeg(processedFrame, imageQuality);
        } else {
            // Histogram equalization using YCrCb
            Imgproc.cvtColor(sourceFrame, ycrcb, Imgproc.COLOR_YUV2RGBA_NV21, 4);
            Imgproc.cvtColor(ycrcb, ycrcb, Imgproc.COLOR_RGB2YCrCb);
            Core.split(ycrcb, channels);
            Imgproc.equalizeHist(channels.get(0), channels.get(0));
            Core.merge(channels, processedFrame);
            Imgproc.cvtColor(processedFrame, processedFrame, Imgproc.COLOR_YCrCb2BGR);
            return CvUtils.toJpegByteArray(processedFrame, imageQuality);
        }
    } catch (Exception e) {
        LOGE(TAG, "[process] Unable to process byte[]", e);
        return null;
    }
}

结果

对于伽马校正,

private void configureLut() {
    releaseMat(lutMat);
    lutMat = new Mat(1, 256, CvType.CV_8UC1);
    double invGamma = 1.0 / gamma;
    int size = (int) (lutMat.total() * lutMat.channels());
    byte[] temp = new byte[size];
    lutMat.get(0, 0, temp);
    for (int j = 0; j < 256; ++j) {
        temp[j] = (byte) (Math.pow((double) j / 255.0, invGamma) * 255.0);
    }
    lutMat.put(0, 0, temp);
}

@Override
public byte[] process(final byte[] source) {
    try {
        if (source == null) return null;
        if (sourceFrame == null) {
            sourceFrame = new Mat(height + (height / 2), width, CvType.CV_8UC1);
            processedFrame = new Mat(height + (height / 2), width, CvType.CV_8UC1);
        }
        sourceFrame.put(0, 0, source);

        // Gamma correction
        if (isColor) {
            Imgproc.cvtColor(sourceFrame, processedFrame, Imgproc.COLOR_YUV2BGRA_NV21);
            Core.LUT(processedFrame, lutMat, processedFrame);

            // Convert to JPEG
            return CvUtils.toJpegByteArray(processedFrame, imageQuality);
        } else {
            Imgproc.cvtColor(sourceFrame, processedFrame, Imgproc.COLOR_YUV420p2GRAY);
            Core.LUT(processedFrame, lutMat, processedFrame);

            // Convert to JPEG
            return CvUtils.grayToJpeg(processedFrame, imageQuality);
        }
    } catch (Exception e) {
        LOGE(TAG, "[process] Unable to process byte[]", e);
        return null;
    }
}

 

要查看完整的源代码,请查看 GitHub 仓库。

历史

2016-10-01 - 初始发布。

© . All rights reserved.