繁体   English   中英

有没有一种在数据库中存储Opencv / javacv Mat对象的方法?

[英]Is there a way of storing Opencv/javacv Mat objects in a database?

在阅读了无休止的文档并尝试理解有关opencv / javacv的示例以提取关键点之后,使用一些DescriptorExtractor计算功能以将输入图像与一堆图像进行匹配,以查看输入图像是其中之一还是其​​中一部分,我认为,我们应该在计算Mat对象后将其存储。

我将使用Emily Webb的代码作为示例:

字符串smallUrl =“ rsz_our-mobile-planet-us-infographic_infographics_lg_unberela.jpg”; 字符串largeUrl =“ our-mobile-planet-us-infographic_infographics_lg.jpg”;

IplImage image = cvLoadImage(largeUrl,CV_LOAD_IMAGE_UNCHANGED );
IplImage image2 = cvLoadImage(smallUrl,CV_LOAD_IMAGE_UNCHANGED ); 

CvMat descriptorsA = new CvMat(null);
CvMat descriptorsB = new CvMat(null);

final FastFeatureDetector ffd = new FastFeatureDetector(40, true);
final KeyPoint keyPoints = new KeyPoint();
final KeyPoint keyPoints2 = new KeyPoint();

ffd.detect(image, keyPoints, null);
ffd.detect(image2, keyPoints2, null);

System.out.println("keyPoints.size() : "+keyPoints.size());
System.out.println("keyPoints2.size() : "+keyPoints2.size());
 // BRISK extractor = new  BRISK();
 //BriefDescriptorExtractor extractor = new BriefDescriptorExtractor();
FREAK extractor = new FREAK();

extractor.compute(image, keyPoints, descriptorsA);
extractor.compute(image2, keyPoints2, descriptorsB);

System.out.println("descriptorsA.size() : "+descriptorsA.size());
System.out.println("descriptorsB.size() : "+descriptorsB.size());

DMatch dmatch = new DMatch();
//FlannBasedMatcher matcher = new FlannBasedMatcher();
//DescriptorMatcher matcher = new DescriptorMatcher();

BFMatcher matcher = new BFMatcher();
matcher.match(descriptorsA, descriptorsB, dmatch, null);

System.out.println(dmatch.capacity());

我的问题是:如何在DBc中以opencv-的Java实现存储描述符A(或描述符B)? (它们是在extractor.compute(image,keyPoints,descriptorsA);之后获得的Mat对象。)

我知道以下事实:Mat对象在Java实现中不是可序列化的对象,但是可以肯定的是,如果要将图像与一组存档图像进行匹配,则必须提取存档的描述符,并将其存储在某些位置以供功能使用..

经过更多搜索后,我在http://answers.opencv.org/question/8873/best-way-to-store-a-mat-object-in-android/中找到了一些链接

尽管答案主要是针对android设备的,并且参考了有关保存关键点的早期问题( 使用OpenCV4Android(java API)保存ORB特征向量 ),但是以下代码中的答案“从Mat对象到xml,从xml到Mat对象”似乎是工作:

import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.util.Locale;
import java.util.Scanner;

public class TaFileStorage {
    // static
    public static final int READ = 0;
    public static final int WRITE = 1;

    // varaible
    private File file;
    private boolean isWrite;
    private Document doc;
    private Element rootElement;

    public TaFileStorage() {
        file = null;
        isWrite = false;
        doc = null;
        rootElement = null;
    }


    // read or write
    public void open(String filePath, int flags ) {
        try {
            if( flags == READ ) {
                open(filePath);
            }
            else {
                create(filePath);
            }
        } catch(Exception e) {
            e.printStackTrace();
        }

    }


    // read only
    public void open(String filePath) {
        try {
            file = new File(filePath);
            if( file == null || file.isFile() == false ) {
                System.err.println("Can not open file: " + filePath );
            }
            else {
                isWrite = false;
                doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file);
                doc.getDocumentElement().normalize();
            }
        } catch(Exception e) {
            e.printStackTrace();
        }

    }

    // write only
    public void create(String filePath) {
        try {
            file = new File(filePath);
            if( file == null ) {
                System.err.println("Can not wrtie file: " + filePath );
            }
            else {
                isWrite = true;
                doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

                rootElement = doc.createElement("opencv_storage");
                doc.appendChild(rootElement);
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public Mat readMat(String tag) {
        if( isWrite ) {
            System.err.println("Try read from file with write flags");
            return null;
        }

        NodeList nodelist = doc.getElementsByTagName(tag);
        Mat readMat = null;

        for( int i = 0 ; i<nodelist.getLength() ; i++ ) {
            Node node = nodelist.item(i);

            if( node.getNodeType() == Node.ELEMENT_NODE ) {
                Element element = (Element)node;

                String type_id = element.getAttribute("type_id");
                if( "opencv-matrix".equals(type_id) == false) {
                    System.out.println("Fault type_id ");
                }

                String rowsStr = element.getElementsByTagName("rows").item(0).getTextContent();
                String colsStr = element.getElementsByTagName("cols").item(0).getTextContent();
                String dtStr = element.getElementsByTagName("dt").item(0).getTextContent();
                String dataStr = element.getElementsByTagName("data").item(0).getTextContent();

                int rows = Integer.parseInt(rowsStr);
                int cols = Integer.parseInt(colsStr);
                int type = CvType.CV_8U;

                Scanner s = new Scanner(dataStr);
                s.useLocale(Locale.US);

                if( "f".equals(dtStr) ) {
                    type = CvType.CV_32F;
                    readMat = new Mat( rows, cols, type );
                    float fs[] = new float[1];
                    for( int r=0 ; r<rows ; r++ ) {
                        for( int c=0 ; c<cols ; c++ ) {
                            if( s.hasNextFloat() ) {
                                fs[0] = s.nextFloat();
                            }
                            else {
                                fs[0] = 0;
                                System.err.println("Unmatched number of float value at rows="+r + " cols="+c);
                            }
                            readMat.put(r, c, fs);
                        }
                    }
                }
                else if( "i".equals(dtStr) ) {
                    type = CvType.CV_32S;
                    readMat = new Mat( rows, cols, type );
                    int is[] = new int[1];
                    for( int r=0 ; r<rows ; r++ ) {
                        for( int c=0 ; c<cols ; c++ ) {
                            if( s.hasNextInt() ) {
                                is[0] = s.nextInt();
                            }
                            else {
                                is[0] = 0;
                                System.err.println("Unmatched number of int value at rows="+r + " cols="+c);
                            }
                            readMat.put(r, c, is);
                        }
                    }
                }
                else if( "s".equals(dtStr) ) {
                    type = CvType.CV_16S;
                    readMat = new Mat( rows, cols, type );
                    short ss[] = new short[1];
                    for( int r=0 ; r<rows ; r++ ) {
                        for( int c=0 ; c<cols ; c++ ) {
                            if( s.hasNextShort() ) {
                                ss[0] = s.nextShort();
                            }
                            else {
                                ss[0] = 0;
                                System.err.println("Unmatched number of int value at rows="+r + " cols="+c);
                            }
                            readMat.put(r, c, ss);
                        }
                    }
                }
                else if( "b".equals(dtStr) ) {
                    readMat = new Mat( rows, cols, type );
                    byte bs[] = new byte[1];
                    for( int r=0 ; r<rows ; r++ ) {
                        for( int c=0 ; c<cols ; c++ ) {
                            if( s.hasNextByte() ) {
                                bs[0] = s.nextByte();
                            }
                            else {
                                bs[0] = 0;
                                System.err.println("Unmatched number of byte value at rows="+r + " cols="+c);
                            }
                            readMat.put(r, c, bs);
                        }
                    }
                }
            }
        }
        return readMat;
    }


    public void writeMat(String tag, Mat mat) {
        try {
            if( isWrite == false) {
                System.err.println("Try write to file with no write flags");
                return;
            }

            Element matrix = doc.createElement(tag);
            matrix.setAttribute("type_id", "opencv-matrix");
            rootElement.appendChild(matrix);

            Element rows = doc.createElement("rows");
            rows.appendChild( doc.createTextNode( String.valueOf(mat.rows()) ));

            Element cols = doc.createElement("cols");
            cols.appendChild( doc.createTextNode( String.valueOf(mat.cols()) ));

            Element dt = doc.createElement("dt");
            String dtStr;
            int type = mat.type();
            if(type == CvType.CV_32F ) { // type == CvType.CV_32FC1
                dtStr = "f";
            }
            else if( type == CvType.CV_32S ) { // type == CvType.CV_32SC1
                dtStr = "i";
            }
            else if( type == CvType.CV_16S  ) { // type == CvType.CV_16SC1
                dtStr = "s";
            }
            else if( type == CvType.CV_8U ){ // type == CvType.CV_8UC1 
                dtStr = "b";
            }
            else {
                dtStr = "unknown";
            }
            dt.appendChild( doc.createTextNode( dtStr ));

            Element data = doc.createElement("data");
            String dataStr = dataStringBuilder( mat );
            data.appendChild( doc.createTextNode( dataStr ));

            // append all to matrix
            matrix.appendChild( rows );
            matrix.appendChild( cols );
            matrix.appendChild( dt );
            matrix.appendChild( data );

        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    private String dataStringBuilder(Mat mat) {
        StringBuilder sb = new StringBuilder();
        int rows = mat.rows();
        int cols = mat.cols();
        int type = mat.type();

        if( type == CvType.CV_32F ) {
            float fs[] = new float[1];
            for( int r=0 ; r<rows ; r++ ) {
                for( int c=0 ; c<cols ; c++ ) {
                    mat.get(r, c, fs);
                    sb.append( String.valueOf(fs[0]));
                    sb.append( ' ' );
                }
                sb.append( '\n' );
            }       
        }
        else if( type == CvType.CV_32S ) {
            int is[] = new int[1];
            for( int r=0 ; r<rows ; r++ ) {
                for( int c=0 ; c<cols ; c++ ) {
                    mat.get(r, c, is);
                    sb.append( String.valueOf(is[0]));
                    sb.append( ' ' );
                }
                sb.append( '\n' );
            }
        }
        else if( type == CvType.CV_16S ) {
            short ss[] = new short[1];
            for( int r=0 ; r<rows ; r++ ) {
                for( int c=0 ; c<cols ; c++ ) {
                    mat.get(r, c, ss);
                    sb.append( String.valueOf(ss[0]));
                    sb.append( ' ' );
                }
                sb.append( '\n' );
            }
        }
        else if( type == CvType.CV_8U ) {
            byte bs[] = new byte[1];
            for( int r=0 ; r<rows ; r++ ) {
                for( int c=0 ; c<cols ; c++ ) {
                    mat.get(r, c, bs);
                    sb.append( String.valueOf(bs[0]));
                    sb.append( ' ' );
                }
                sb.append( '\n' );
            }
        }       
        else {
            sb.append("unknown type\n");
        }

        return sb.toString();
    }


    public void release() {
        try {
            if( isWrite == false) {
                System.err.println("Try release of file with no write flags");
                return;
            }

            DOMSource source = new DOMSource(doc);

            StreamResult result = new StreamResult(file);

            // write to xml file
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");

            // do it
            transformer.transform(source, result);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

由于Thorben提出的代码在我看来很慢,因此我想出了以下使用序列化的代码。

public final void saveMat(String path, Mat mat) {
    File file = new File(path).getAbsoluteFile();
    file.getParentFile().mkdirs();
    try {
        int cols = mat.cols();
        float[] data = new float[(int) mat.total() * mat.channels()];
        mat.get(0, 0, data);
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path))) {
            oos.writeObject(cols);
            oos.writeObject(data);
            oos.close();
        }
    } catch (IOException | ClassCastException ex) {
        System.err.println("ERROR: Could not save mat to file: " + path);
        Logger.getLogger(this.class.getName()).log(Level.SEVERE, null, ex);
    }
}

public final Mat loadMat(String path) {
    try {
        int cols;
        float[] data;
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path))) {
            cols = (int) ois.readObject();
            data = (float[]) ois.readObject();
        }
        Mat mat = new Mat(data.length / cols, cols, CvType.CV_32F);
        mat.put(0, 0, data);
        return mat;
    } catch (IOException | ClassNotFoundException | ClassCastException ex) {
        System.err.println("ERROR: Could not load mat from file: " + path);
        Logger.getLogger(this.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
}

对于描述你的OpenCV采用花车垫,在其他情况下,你必须相应地修改代码以这个列表中找到这里

CV_8U and CV_8S -> byte[]
CV_16U and CV_16S -> short[]
CV_32S -> int[]
CV_32F -> float[]
CV_64F-> double[]

搜索完所有答案后,我编辑了一些代码,它似乎可以正常工作。我用它将Sift描述符存储到HBase中。

public static byte[] serializeMat(Mat mat) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            float[] data = new float[(int) mat.total() * mat.channels()];
            mat.get(0, 0, data);
            ObjectOutput out = new ObjectOutputStream(bos);
            out.writeObject(data);
            out.close();
            // Get the bytes of the serialized object
            byte[] buf = bos.toByteArray();
            return buf;
        } catch (IOException ioe) {
            ioe.printStackTrace();
            return null;
        }
    }

暂无
暂无

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

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