簡體   English   中英

將色彩通道從BGR轉換為RGB

[英]Convert color channels from BGR to RGB

我正在使用OpenCV進行視頻捕獲項目。 我已經能夠使視頻捕獲正常工作,但是我想將攝像機濾鏡更改為“常規”光譜,以便香蕉不是藍色的,而是黃色的。 這就是RGB光譜。 我在for循環中的程序中進行了轉換,但相機視圖仍然是BRG。 這是一張圖片。 在此處輸入圖片說明

如何獲得顯示“真實”顏色的圖像視圖? 這是我的代碼。

墊到圖像類

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);
    }
}

視頻拍攝類

    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);
    }
}

我的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) {    }
            }  
        } 
    }
}

您正在對顏色進行錯誤的重新排列-您的移位不夠大,應該使用OR( | )而不是AND( & )運算符來重新組合顏色。

您的代碼:

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

應該變成:

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

編輯

此外,看起來您沒有在目標圖像上使用int[] ,而是在顏色上使用了3字節的編碼。 因此,您更有可能需要執行以下操作:

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;

但是對於我來說,現在還不清楚是從BGR變為RGB,還是從RGB變為BGR。 您可能需要更改最后3個作業的順序才能正確執行此操作。

昨天我花了一些時間試圖將其分解,最終使它起作用。 我要做的第一件事是分配新圖像。 這是在getSpace完成的。 然后,我轉換分配的圖像,然后從矩陣中捕獲數據,然后將數據放入圖像中。 最后3個步驟全部在getImage 這是我解決的方法。

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;
}

Mat2Image類的其余代碼應與我未在答案中添加的代碼相同,您可以嘗試一下。 :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM