2014-10-18 48 views
1

在閱讀了無盡的文檔並試圖理解關於提取關鍵點的opencv/javacv示例之後,使用一些DescriptorExtractors計算要素以匹配輸入圖像與一堆圖像以查看輸入圖像是其中的一個還是其中一個的一部分我認爲,我們應該在計算它們後存儲Mat對象。有沒有辦法將Opencv/javacv Mat對象存儲在數據庫中?

我將使用Emily Webb' S碼作爲示例:

字符串smallUrl = 「rsz_our移動行星-US-infographic_infographics_lg_unberela.jpg」; String 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()); 

我的問題是: 我如何可以存儲descriptorsA(或descriptorsB)在DB --in java實現opencv-的? (它們是Mat extractor.compute(image,keyPoints,descriptorsA)後得到的對象;)

我意識到Mat對象在java實現中不是可序列化的對象,但肯定如果您想匹配映像一組存檔圖像,你雖然答案主要用於提取歸檔的描述,並存儲它們的功能使用的一些地方..

+0

它們必須被序列化*以某種方式*之前,它們可以存儲。 – user2864740 2014-10-19 00:14:27

+0

'cv :: imwrite()'或'cvSaveImage()'是*序列化*的方法;) – karlphillip 2014-10-19 01:14:43

+0

由於C++是問題所在的標記之一,因此可以使用'FileStorage'。儘管存儲爲XML或YML文件。這是否符合你的目的? – 2014-10-19 05:53:22

回答

4

後一些更多的搜索,我發現一些鏈接在http://answers.opencv.org/question/8873/best-way-to-store-a-mat-object-in-android/

Android設備,並提到有關保存關鍵點(Saving ORB feature vectors using OpenCV4Android (java API))的早期問題,答案是「從Mat object到xml以下XML代碼中的墊目標」似乎是工作:

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(); 
     } 
    } 
} 
+0

不錯的代碼。謝謝。當您嘗試使用Scanner類讀取時,我剛糾正了與系統區域相關的錯誤。非常偷偷摸摸。我還添加了進口 - 認爲它們可能有用。 – Thorben 2015-11-02 20:20:46

1

正如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採用花車墊,在其他情況下,你必須相應地修改代碼以這個列表中找到here

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

搜索後,所有的答案,我修改一些代碼它似乎work.I使用它來存儲篩選描述符到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; 
     } 
    } 
相關問題