简体   繁体   English

将色彩通道从BGR转换为RGB

[英]Convert color channels from BGR to RGB

I am working on a video capture project with OpenCV. 我正在使用OpenCV进行视频捕获项目。 I have been able to get the video capture to work but I want to change the camera filter to the "regular" spectrum so that the banana isn't blue and is yellow lol. 我已经能够使视频捕获正常工作,但是我想将摄像机滤镜更改为“常规”光谱,以便香蕉不是蓝色的,而是黄色的。 This would be the RGB spectrum. 这就是RGB光谱。 I do the conversions in my program in the for loop but my camera view is still BRG. 我在for循环中的程序中进行了转换,但相机视图仍然是BRG。 Here is an image. 这是一张图片。 在此处输入图片说明

How can I get the image view to show "true" colors? 如何获得显示“真实”颜色的图像视图? Here is my code. 这是我的代码。

Mat to Image Class 垫到图像类

import java.awt.Color;
import java.awt.image.BufferedImage;
import org.opencv.core.Core;
import org.opencv.core.Mat;

public class Mat2Image {
    Mat mat = new Mat();
    private int argb = 0;
    Color c = new Color(argb, true);
    BufferedImage img;
    byte [] dat;

    Mat2Image(){
    }

    public Mat2Image(Mat mat) {
        getSpace(mat);
    }

    public void getSpace(Mat mat) {
        this.mat = mat;
        int w = mat.cols(), h = mat.rows();
        if (dat == null || dat.length != w * h * 3)
            dat = new byte[w * h * 3];
        if (img == null || img.getWidth() != w || img.getHeight() != h || img.getType() != BufferedImage.TYPE_3BYTE_BGR)
            img = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);

        int[] holder = new int[w * h];
        holder =  img.getData().getPixels(0, 0, w, h, (int[]) null);
        for (int i = 0; i < dat.length; i++) {

            int blueChannel = (holder[i] & 0xFF0000) >> 4;
            int greenChannel = (holder[i] & 0xFF00) >> 2;
            int redChannel = (holder[i] & 0xFF);
            int rgb = (blueChannel) & (greenChannel << 2) & (redChannel << 4);

            dat[i] = (byte) rgb;
        }
    }   

    BufferedImage getImage(Mat mat) {
        getSpace(mat);
        mat.get(0, 0, dat);
        img.getRaster().setDataElements(0, 0, mat.cols(), mat.rows(), dat);
        return img;
    }
    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }
}

Video Capture Class 视频拍摄类

    public class VideoCap {
    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }
    int currFrame = 0;
    VideoCapture cap;
    Mat2Image mat2Img = new Mat2Image();

    VideoCap() {
        cap = new VideoCapture();
        cap.open(0);
    }

    BufferedImage getOneFrame() {
        currFrame++;
        //currFrame is just to stop the camera of after the running for a bit.
        if (currFrame == 20) {
            cap.read(mat2Img.mat);
            System.exit(0);
        }
        cap.read(mat2Img.mat);

        return mat2Img.getImage(mat2Img.mat);
    }
}

My JFrame Class 我的JFrame类

    public class MyFrame extends JFrame {
    private JPanel contentPane;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    MyFrame frame = new MyFrame();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public MyFrame() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100,100,650,490);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5,5,5,5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        new MyThread().start();
    }

    VideoCap videoCap = new VideoCap();

    public void paint(Graphics g){
        g = contentPane.getGraphics();
        g.drawImage(videoCap.getOneFrame(), 0, 0, this);
    }

    class MyThread extends Thread{
        @Override
        public void run() {
            for (;;){
                repaint();
                try { Thread.sleep(30);
                } catch (InterruptedException e) {    }
            }  
        } 
    }
}

You're doing the rearranging of the colors wrong - you're not shifting by enough bits, and you should be using the OR ( | ) rather than the AND ( & ) operator to recombine the color. 您正在对颜色进行错误的重新排列-您的移位不够大,应该使用OR( | )而不是AND( & )运算符来重新组合颜色。

Your code: 您的代码:

int blueChannel = (holder[i] & 0xFF0000) >> 4;
int greenChannel = (holder[i] & 0xFF00) >> 2;
int redChannel = (holder[i] & 0xFF);
int rgb = (blueChannel) & (greenChannel << 2) & (redChannel << 4);

Should become: 应该变成:

int blueChannel = (holder[i] & 0xFF0000) >> 16;
int greenChannel = (holder[i] & 0xFF00) >> 8;
int redChannel = (holder[i] & 0xFF);
int rgb = (blueChannel) | (greenChannel << 8) | (redChannel << 16);

EDIT 编辑

Furthermore, it looks like you're not using an int[] for your target image, but rather a 3-byte encoding for the color. 此外,看起来您没有在目标图像上使用int[] ,而是在颜色上使用了3字节的编码。 So it's more likely that you need to do: 因此,您更有可能需要执行以下操作:

for (int i = 0; i < holder.length; i++) {
    byte blueChannel = (byte) ((holder[i] & 0xFF0000) >> 16);
    byte greenChannel = (byte) ((holder[i] & 0xFF00) >> 8);
    byte redChannel = (byte) (holder[i] & 0xFF);

    dat[i*3] = redChannel;
    dat[i*3+1] = greenChannel;
    dat[i*3+2] = blueChannel;

But it's not clear to me anymore whether you are going from BGR to RGB or the reverse from RGB to BGR. 但是对于我来说,现在还不清楚是从BGR变为RGB,还是从RGB变为BGR。 You may need to change the order of the last 3 assignments to get this right. 您可能需要更改最后3个作业的顺序才能正确执行此操作。

I spent time yesterday trying to break it down and I finally got it to work. 昨天我花了一些时间试图将其分解,最终使它起作用。 The first thing I did was allocate for the new image. 我要做的第一件事是分配新图像。 which is done in getSpace . 这是在getSpace完成的。 Then I convert the allocated image, then capture the data from the matrix, then put the data into the image. 然后,我转换分配的图像,然后从矩阵中捕获数据,然后将数据放入图像中。 The last 3 steps all take place in getImage . 最后3个步骤全部在getImage Here is how I solved it. 这是我解决的方法。

public void getSpace(Mat mat) {
    this.mat = mat;
    int w = mat.cols(), h = mat.rows();
    if (dat == null || dat.length != w * h * 3)
        dat = new byte[w * h * 3];
    if (img == null || img.getWidth() != w || img.getHeight() != h || img.getType() != BufferedImage.TYPE_3BYTE_BGR)
        img = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);


}

BufferedImage getImage(Mat mat) {
    getSpace(mat);
    mat.get(0, 0, dat);

    for (int i = 0; i < dat.length; i+= 3) {
        byte redChannel = dat[i];
        byte blueChannel = dat[i+2];

        dat[i] = blueChannel;
        dat[i+2] = redChannel;

    }
    img.getRaster().setDataElements(0, 0, mat.cols(), mat.rows(), dat);
    return img;
}

The remaining code from the Mat2Image class should be the same that I didn't add in the answer and you can try it out. Mat2Image类的其余代码应与我未在答案中添加的代码相同,您可以尝试一下。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM