zoukankan      html  css  js  c++  java
  • BufferedImage(JDK)<----interoperate---->Mat(OpenCV)

    Alpha Channel Support

    OpenCV 不支持 alpha channel, 只支持masking;但是BufferedImage支持alpha。那么怎样获取BufferedImage img 的数据呢?目前有两种方法:

    (1)img.getRGB(0, 0, w, h, pixels, 0, w);//这里的pixels是int[]型。每一个int四个字节,第一个是alpha值,之后分别是BGR值。当然这是对于TYPE_3BYTE_BGR类型而言的。 之所以列举这种类型是因为项目中的图像是这种类型。如下:

    BufferedImahe img=ImageIO.read(new File("***"));
    int[] rgb=new int[w*h];
    img.getRGB(0,0,w,h,rgb,0,w); byte r=(rgb[0]&ff); byte g=(rgb[0]>>8)&ff; byte b=(rgb[0]>>16)&ff

    注意:TYPE_3BYTE_BGR Represents an image with 8-bit RGB color components, corresponding to a Windows-style BGR color model) with the colors Blue, Green, and Red stored in 3 bytes. There is no alpha. The image has a ComponentColorModel. When data with non-opaque alpha is stored in an image of this type, the color data must be adjusted to a non-premultiplied form and the alpha discarded。

    (2)byte[] pixels =((DataBufferByte) img.getRaster().getDataBuffer()).getData();这里直接是将(1)中的每一个int转换为了3个byte,这3个byte分别对应bgr,这里没有了alpha。没有了alpha。。。。那部是和OpenCV的数据结构更加相似了吗?!

            BufferedImage img=ImageIO.read(new File("/home/chase/Pictures/hand.png"));
        	System.out.println(img.getType());
        	int w=img.getWidth();
        	int h=img.getHeight();
        	System.out.println(h+" "+w+" "+w*h);
        	int[]bgr=new int[w*h];
        	img.getRGB(0, 0, w, h, bgr, 0, w);
        	byte[] by=((DataBufferByte)img.getRaster().getDataBuffer()).getData();
        	System.out.println(by.length);
        	int r=(bgr[3] & 0xff);System.out.println("r:"+r);
        	int g=(bgr[3] & 0xff00)>>8;System.out.println("g:"+g);
        	int b=(bgr[3] & 0xff0000)>>16;System.out.println("b:"+b);
        	System.out.println("b:"+by[9]);
        	System.out.println("g:"+by[10]);
        	System.out.println("r:"+by[11]);

    问题:但是我好像发现(1)(2)中的rgb[i]和pixels[3*i],pixels[3*i+1],pixels[3*i+2]不对应。rgb[i]中的24bit是【alpha】【B】【G】【R】,然而pixels[3*i],pixels[3*i+1],pixels[3*i+2]对应的顺序是【R】【G】【B】。但是这应该没什么关系吧我觉得。

    TYPE_3BYTE_BGR 型图像是CS_sRGB标准彩色模型。

    BufferedImage-->Mat

     用OpenCV显示一张Bufferedmage

    cpp代码:

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    #include <opencv2/opencv.hpp>
    using namespace std;
    using namespace cv;
    /* Header for class gmmopencv_BufferedImg2Mat */
    
    #ifndef _Included_gmmopencv_BufferedImg2Mat
    #define _Included_gmmopencv_BufferedImg2Mat
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     gmmopencv_BufferedImg2Mat
     * Method:    JNIShowBufferedImg
     * Signature: (III[B)V
     */
    JNIEXPORT void JNICALL Java_gmmopencv_BufferedImg2Mat_JNIShowBufferedImg(JNIEnv *env, jobject, jint w, jint h, jint comps, jbyteArray pixels)
    {
            IplImage* img=cvCreateImageHeader(cvSize(w,h),8,comps);
            jbyte*pixel=env->GetByteArrayElements(pixels, 0);
            cvSetData(img,pixel,3*w);
            Mat frame=Mat(img);
            imshow("image",frame);
            cvWaitKey(0);
            env->ReleaseByteArrayElements(pixels,pixel, 0);
    }
    
    #ifdef __cplusplus
    }
    #endif
    #endif

    java代码:

    package gmmopencv;
    
    import java.awt.image.BufferedImage;
    import java.awt.image.DataBufferByte;
    import java.io.File;
    import java.io.IOException;
    
    import javax.imageio.ImageIO;
    
    public class BufferedImg2Mat {
        public native void JNIShowBufferedImg(int w,int h,int num_of_channel,byte[]pixels);
        static{System.loadLibrary("jnishowimg");}
        public static void main(String args[]) throws IOException{
            BufferedImage img=ImageIO.read(new File("/home/chase/Pictures/desktop.jpg"));
            int w=img.getWidth();
            int h=img.getHeight();
            int comps=img.getColorModel().getNumColorComponents();
            byte[] pixels=((DataBufferByte)img.getRaster().getDataBuffer()).getData();
            new BufferedImg2Mat().JNIShowBufferedImg(w, h, comps, pixels);
        }
    }

    具体怎样使用这个JNI,以及我一值bug的一些问题,参考:Install (JDK+Eclipse)--->Try JNI--->Some issues

     用OpenCV显示连续BufferedImage图片序列

    我们使用的云视频项目,需要从摄像头里面提取连续的帧序列,所以需要连续显示。cpp代码与显示单张的代码唯一区别就是cvWaitKey(x)。如下所示:

     1 /* DO NOT EDIT THIS FILE - it is machine generated */
     2 #include <jni.h>
     3 #include <opencv2/opencv.hpp>
     4 using namespace std;
     5 using namespace cv;
     6 /* Header for class showjnimat_JNIMat */
     7 
     8 #ifndef _Included_showjnimat_JNIMat
     9 #define _Included_showjnimat_JNIMat
    10 #ifdef __cplusplus
    11 extern "C" {
    12 #endif
    13 /*
    14  * Class:     showjnimat_JNIMat
    15  * Method:    JNIShowBufferedImg
    16  * Signature: (III[B)V
    17  */
    18 Mat frame;
    19 JNIEXPORT void JNICALL Java_showjnimat_JNIMat_JNIShowBufferedImg(JNIEnv *env, jobject, jint w, jint h, jint comps, jbyteArray pixels)
    20 {
    21         IplImage* img=cvCreateImageHeader(cvSize(w,h),8,comps);
    22         jbyte*pixel=env->GetByteArrayElements(pixels, 0);
    23         cvSetData(img,pixel,3*w);
    24         frame=Mat(img);
    25         imshow("image",frame);
    26         char c=cv::waitKey(33);
    27         env->ReleaseByteArrayElements(pixels,pixel, 0);
    28 
    29 }
    30 
    31 #ifdef __cplusplus
    32 }
    33 #endif
    34 #endif

    java代码可能区别大了一点,因为涉及到连续帧的提取问题。如下所示:

     1 package showjnimat;
     2 
     3 import java.awt.image.BufferedImage;
     4 import java.awt.image.DataBufferByte;
     5 import java.net.MalformedURLException;
     6 import java.util.Date;
     7 
     8 import com.github.sarxos.webcam.Webcam;
     9 import com.github.sarxos.webcam.WebcamDevice;
    10 import com.github.sarxos.webcam.ds.ipcam.IpCamDeviceRegistry;
    11 import com.github.sarxos.webcam.ds.ipcam.IpCamDriver;
    12 import com.github.sarxos.webcam.ds.ipcam.IpCamMode;
    13 
    14 public class JNIMat {
    15     public native void JNIShowBufferedImg(int w,int h,int comps,byte[]pixels);
    16     static{
    17         System.loadLibrary("jnishowimg");
    18         Webcam.setDriver(new IpCamDriver());
    19         }
    20     public static void main(String args[]) throws MalformedURLException, InterruptedException{
    21         IpCamDeviceRegistry.register("ZModo", "http://admin:123456@192.168.1.20:80/videostream.cgi", IpCamMode.PUSH);
    22         WebcamDevice camdevice=Webcam.getWebcams().get(0).getDevice();
    23         
    24         camdevice.open();//MUST OPEN!!!I Bug this for a LONG LONG TIME! OH MY TIME....
    25         JNIMat jnimat=new JNIMat();
    26         BufferedImage img;
    27         int w,h,comps;
    28         byte[] pixels;
    29         while(true){
    30             Date date1=new Date();
    31             long t1=date1.getTime();
    32             img=camdevice.getImage();
    33             w=img.getWidth();
    34             h=img.getHeight();
    35             comps=img.getColorModel().getNumColorComponents();
    36             pixels=((DataBufferByte)img.getRaster().getDataBuffer()).getData();
    37             jnimat.JNIShowBufferedImg(w, h, comps, pixels);
    38             Date date2=new Date();
    39             long t2=date2.getTime();
    40             System.out.println(1000f/(t2-t1));
    41         }
    42     }
    43 
    44 }

     Mat---->BufferedImage

    这一部分在我这里主要设计对一个CV_8U的Mat转化为BufferedImage二值图像。分为两部分,第一部分是在JNI本地代码中实现的,第二部分是在java中实现的。第一部分返回一个byte[],第二部分将这个byte[]弄成一个java二值图像。

    第一部分代码:

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    #include <iostream>
    #include <string>
    #include <opencv2/opencv.hpp>
    using namespace std;
    using namespace cv;
    /* Header for class upc_se_intelmonitor_GMM4BgS */
    
    #ifndef _Included_upc_se_intelmonitor_GMM4BgS
    #define _Included_upc_se_intelmonitor_GMM4BgS
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     upc_se_intelmonitor_GMM4BgS
     * Method:    subtract
     * Signature: (II[B)[B
     */
    BackgroundSubtractorMOG2 mog;
    Mat fg;
    Mat frame;
    
    JNIEXPORT jbyteArray JNICALL Java_upc_se_intelmonitor_GMM4BgS_subtract
      (JNIEnv *env, jclass, jint w, jint h, jbyteArray bgr)
    {
    IplImage* img=cvCreateImageHeader(cvSize(w,h),8,3);
    jbyte*pixel=env->GetByteArrayElements(bgr, 0);
    cvSetData(img,pixel,3*w);
    frame=cv::Mat(img);
    imshow("raw_frame",frame);
    mog.operator()(frame,fg);
    imshow("fg",fg);
    cvWaitKey(10);
    IplImage p_fg=IplImage(fg);
    
    jbyteArray bArray;
    long length=w*h;
    jbyte*byteArrayElement;
    
    bArray=env->NewByteArray((jsize)length);
    byteArrayElement =env->GetByteArrayElements(bArray,NULL);
    memcpy(byteArrayElement,p_fg.imageData,length);
    //cvGetRawData(&p_frame,(uchar**)&fg,NULL,NULL);
    env->ReleaseByteArrayElements(bgr,pixel, 0);
    env->ReleaseByteArrayElements(bArray,byteArrayElement, 0);
    return  bArray;
    }
    
    #ifdef __cplusplus
    }
    #endif
    #endif

    另外,还有一个版本,就是不用memcpy,关键部分如下

    jbyteArray bArray;
    long length=fg.rows*fg.cols;
    jbyte*byteArrayElement;
    
    bArray=env->NewByteArray((jsize)length);
    //byteArrayElement =env->GetByteArrayElements(bArray,NULL);
    //memcpy(byteArrayElement,p_fg.imageData,length);
    env->SetByteArrayRegion(bArray,0,length,(jbyte*)p_fg.imageData);
    env->ReleaseByteArrayElements(bgr,pixel, 0);
    //env->ReleaseByteArrayElements(bArray,byteArrayElement, 0);
    return  bArray;

    第二部分代码:

    package upc.se.intelmonitor;
    
    import java.awt.image.BufferedImage;
    import java.awt.image.DataBufferByte;
    import java.awt.image.IndexColorModel;
    import java.awt.image.WritableRaster;
    
    import java.io.IOException;
    
    import bwimage.ShowImage;
    
    import com.github.sarxos.webcam.Webcam;
    import com.github.sarxos.webcam.WebcamDevice;
    import com.github.sarxos.webcam.ds.ipcam.IpCamDeviceRegistry;
    import com.github.sarxos.webcam.ds.ipcam.IpCamDriver;
    import com.github.sarxos.webcam.ds.ipcam.IpCamMode;
    
    
    
    public class GMM4BgS {
        static {
            Webcam.setDriver(new IpCamDriver());
        }
        static {
            System.out.println(System.getProperty("java.library.path"));
            System.loadLibrary("GMM4BgS");
            }
        public static native byte[] subtract(int w,int h,byte[]bgr);
        
        public static void main(String args[]) throws IOException{
            IpCamDeviceRegistry.register("ZModo", "http://admin:123456@192.168.1.20:80/videostream.cgi", IpCamMode.PUSH);
            WebcamDevice dev=Webcam.getWebcams().get(0).getDevice();
            dev.open();
            BufferedImage img=dev.getImage();
            byte[] bw = {(byte) 0, (byte) 0xff};
            IndexColorModel blackAndWhite = new IndexColorModel(1, 2, bw, bw, bw);
            BufferedImage fg_img = new BufferedImage(img.getWidth(),img.getHeight(),BufferedImage.TYPE_BYTE_BINARY,blackAndWhite);
             WritableRaster raster = fg_img.getRaster();
             ShowImage s=new ShowImage(fg_img);
            int count=0;
            while(count<3000){
                img=dev.getImage();
                int w=img.getWidth();
                int h=img.getHeight();
                byte[]pixels=((DataBufferByte)img.getRaster().getDataBuffer()).getData();
                byte[]fg=GMM4BgS.subtract(w, h,pixels);
                raster.setDataElements(0, 0, w, h,fg);
                s.SetImage(fg_img);
                s.draw();
                count++;
            }
        }
    }

    这里使用了一个ipcamera,和一个ShowImage,去分别获得和显示图像序列。其中ShowImage代码如下:

    package bwimage;
    
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    
    import javax.imageio.ImageIO;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    
    public class ShowImage extends JComponent{
        private static final long serialVersionUID = 1L;
        static JFrame frame = new JFrame("frame");
        BufferedImage b_img;
        
        public ShowImage(BufferedImage img){
            super();
            this.setOpaque(false);
            b_img=img;
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
            frame.setLayout(new BorderLayout());
            frame.getContentPane().add(this, BorderLayout.CENTER);  
            frame.setPreferredSize(new Dimension(640,480));  
            frame.pack();  
            frame.setVisible(true); 
        }
        
        public void SetImage(BufferedImage img){
            b_img=img;
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            // TODO Auto-generated method stub
            super.paintComponent(g);
            Graphics2D g2=(Graphics2D)g;
            g2.drawImage(b_img, 0, 0,null);
        }
        
        public void draw(){
            
            repaint();
        }
        
        public static void main(String args[]) throws IOException{
            BufferedImage img=ImageIO.read(new File("lena.jpg"));
            ShowImage s=new ShowImage(img);
            s.draw();
        }
        
    
        
        
    
    }

     Split Mat and return to byte[] in Java

    2014-04-09 11:16:32

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    #include <iostream>
    #include <opencv2/opencv.hpp>
    using namespace std;
    using namespace cv;
    /* Header for class upc_se_intelmonitor_SplitImage */
    
    #ifndef _Included_upc_se_intelmonitor_SplitImage
    #define _Included_upc_se_intelmonitor_SplitImage
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     upc_se_intelmonitor_SplitImage
     * Method:    split
     * Signature: (III[B)[B
     */
    JNIEXPORT jbyteArray JNICALL Java_upc_se_intelmonitor_SplitImage_split
      (JNIEnv *env, jclass, jint w, jint h, jint whichpart, jbyteArray bgr)
    {
    IplImage*img=cvCreateImageHeader(cvSize(w,h),8,3);
    jbyte*pixel=env->GetByteArrayElements(bgr,0);
    cvSetData(img,pixel,3*w);
    Mat org_img=Mat(img);
    
    Mat m_part;
    if(whichpart==1)m_part=org_img(Rect(0,0,w,h/3)).clone();
    else if(whichpart==2)m_part=org_img(Rect(0,h/3,w,h/3)).clone();
    else if(whichpart==3)m_part=org_img(Rect(0,(h/3)*2,w,h/3)).clone();
    else cerr<<"whichpart must be 1/2/3";
    IplImage ipl_part=IplImage(m_part);
    
    long part_len=m_part.cols*m_part.rows*3;
    jbyteArray new_partArray=env->NewByteArray((jsize)part_len);
    jbyte*new_partElem=env->GetByteArrayElements(new_partArray,NULL);
    memcpy(new_partElem,ipl_part.imageData,part_len);
    
    env->ReleaseByteArrayElements(bgr,pixel, 0);
    env->ReleaseByteArrayElements(new_partArray,new_partElem, 0);
    
    return new_partArray;
    
    }
    
    #ifdef __cplusplus
    }
    #endif
    #endif

    Merge 多个 byte[] in Java to a Mat

    #include <iostream>
    #include <opencv2/opencv.hpp>
    using namespace std;
    using namespace cv;
    /* Header for class upc_se_intelmonitor_MergeImage */
    
    #ifndef _Included_upc_se_intelmonitor_MergeImage
    #define _Included_upc_se_intelmonitor_MergeImage
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     upc_se_intelmonitor_MergeImage
     * Method:    merge
     * Signature: (II[B[B[B)[B
     */
    JNIEXPORT jbyteArray JNICALL Java_upc_se_intelmonitor_MergeImage_merge
      (JNIEnv *env, jclass, jint w, jint num, jbyteArray part1, jbyteArray part2, jbyteArray part3)
    {
    IplImage*img1=cvCreateImageHeader(cvSize(w,num),8,3);
    jbyte*pixel1=env->GetByteArrayElements(part1,0);
    cvSetData(img1,pixel1,3*w);
    Mat mat1=Mat(img1);
    
    IplImage*img2=cvCreateImageHeader(cvSize(w,num),8,3);
    jbyte*pixel2=env->GetByteArrayElements(part2,0);
    cvSetData(img2,pixel2,3*w);
    Mat mat2=Mat(img2);
    
    IplImage*img3=cvCreateImageHeader(cvSize(w,num),8,3);
    jbyte*pixel3=env->GetByteArrayElements(part3,0);
    cvSetData(img3,pixel3,3*w);
    Mat mat3=Mat(img3);
    
    mat1.push_back(mat2);
    mat1.push_back(mat3);
    IplImage i_img=IplImage(mat1);
    
    long len=w*num*3*3;
    jbyteArray new_Array=env->NewByteArray((jsize)len);
    jbyte*new_Elem=env->GetByteArrayElements(new_Array,NULL);
    memcpy(new_Elem,i_img.imageData,len);
    
    env->ReleaseByteArrayElements(part1,pixel1, 0);
    env->ReleaseByteArrayElements(part2,pixel2, 0);
    env->ReleaseByteArrayElements(part3,pixel3, 0);
    
    env->ReleaseByteArrayElements(new_Array,new_Elem, 0);
    
    return new_Array;
    }
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    ~                                                                                                                                                                                                            
                                                                                                                                                                                               58,1          Bot
  • 相关阅读:
    Python爬虫进阶五之多线程的用法
    Python爬虫进阶四之PySpider的用法
    Python爬虫进阶三之Scrapy框架安装配置
    Python爬虫进阶二之PySpider框架安装配置
    Python爬虫进阶一之爬虫框架概述
    Python爬虫利器六之PyQuery的用法
    Python爬虫利器五之Selenium的用法
    Python爬虫利器四之PhantomJS的用法
    Python爬虫利器三之Xpath语法与lxml库的用法
    Python爬虫利器二之Beautiful Soup的用法
  • 原文地址:https://www.cnblogs.com/chaseblack/p/3585108.html
Copyright © 2011-2022 走看看