【问题标题】:Java OpenCV FileStorage and Mat.push_backJava OpenCV FileStorage 和 Mat.push_back
【发布时间】:2016-07-07 10:20:10
【问题描述】:

我正在尝试用 Java 为 KNN 分类器实现 this 项目,即 GenData.cpp(用 C++ 编写)。
我已经到达这些代码行并卡住了:

matClassificationInts.push_back(intChar);
cv::FileStorage fsClassifications("classifications.xml", cv::FileStorage::WRITE);
fsClassifications << "classifications" << matClassificationInts;
fsClassifications.release();

在 c++ 中,我们可以将整数传递给 push_back(),但在 Java 中我收到错误:“int cannot be convert to Mat”。
所以,第一个问题是:如何将 int 传递给 someMat.push_back()?
第二个:如何在 Java 中实现 FileStorage 或将 Mat 写入 *.xml 格式(并从 *.xml 读取 Mat)?

到目前为止,我的代码:

    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Scanner;
    import org.opencv.core.Core;
    import static org.opencv.core.CvType.CV_32FC1;
    import org.opencv.core.Mat;
    import org.opencv.core.MatOfInt4;
    import org.opencv.core.MatOfPoint;
    import org.opencv.core.Rect;
    import org.opencv.core.Scalar;
    import org.opencv.core.Size;
    import org.opencv.imgcodecs.Imgcodecs;
    import org.opencv.imgproc.Imgproc;
    import static org.opencv.imgproc.Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C;
    import static org.opencv.imgproc.Imgproc.CHAIN_APPROX_SIMPLE;
    import static org.opencv.imgproc.Imgproc.RETR_EXTERNAL;
    import static org.opencv.imgproc.Imgproc.THRESH_BINARY_INV;

    public class genData {

    private static final int 
            MIN_CONTOUR_AREA = 100,
            RESIZED_IMAGE_WIDTH = 20,
            RESIZED_IMAGE_HEIGHT = 30;

    public static void main(String[] args) throws IOException {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 

        Scanner keyboard = new Scanner(System.in);
        boolean exit = false;

        Mat imgTrainingNumbers;
        Mat imgGrayscale = new Mat();
        Mat imgBlurred = new Mat();
        Mat imgThresh = new Mat();
        Mat imgThreshCopy = new Mat();

        ArrayList<MatOfPoint> ptContours = new ArrayList<MatOfPoint>();
        MatOfInt4 v4iHierarchy;
        Mat matClassificationInts = new Mat();
        Mat matTrainingImagesAsFlattenedFloats = new Mat();

        int[] intValidChars = { '0', '1', '2',
        'A', 'B', 'C'}; //Here I did not make List<Integer>, because I can't pass char to Integer.
        Arrays.sort(intValidChars); //for binary search

        imgTrainingNumbers = Imgcodecs.imread("test.png"); //here Text on white paper.

        if (imgTrainingNumbers.empty()) {
            System.out.println("err");
            return;
        }

        Imgproc.cvtColor(imgTrainingNumbers, imgGrayscale, Imgproc.COLOR_BGR2GRAY);
        Imgproc.GaussianBlur(imgGrayscale, imgBlurred, new Size(5, 5), 0);
        Imgproc.adaptiveThreshold(imgBlurred, imgThresh, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 11, 2);

        /*
        //imshow class implementation (found via google, works properly, but this block is commented for now)
        Imshow im = new Imshow("imgThresh");
        im.showImage(imgThresh);
        imgThreshCopy = imgThresh.clone();
        */

        Imgproc.findContours(imgThreshCopy, ptContours, new Mat(), RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);


        for (int i = 0; i < ptContours.size(); i++) {
            if (Imgproc.contourArea(ptContours.get(i)) > MIN_CONTOUR_AREA) {
                Rect boundingRect = Imgproc.boundingRect(ptContours.get(i));
                Imgproc.rectangle(imgTrainingNumbers, boundingRect.tl(), boundingRect.br(), new Scalar(0, 0, 255), 2);
                Mat matROI = imgThresh.submat(boundingRect.y, boundingRect.y + boundingRect.height, boundingRect.x, boundingRect.x + boundingRect.width);
                Mat matROIResized = new Mat();
                Imgproc.resize(matROI, matROIResized, new Size(RESIZED_IMAGE_WIDTH, RESIZED_IMAGE_HEIGHT));
                /*
                im.showImage(matROI);
                im.showImage(matROIResized);
                im.showImage(imgTrainingNumbers);
                */
                String input = keyboard.nextLine();
                int intChar = (int)input.charAt(0);
                if (Arrays.binarySearch(intValidChars, intChar) >=0) {
                    /*
                    matClassificationInts.push_back(intChar);
                    //Here I'm getting an error.
                    */
                    Mat matImageFloat = new Mat();
                    matROIResized.convertTo(matImageFloat, CV_32FC1);
                    Mat matImageFlattenedFloat = matImageFloat.reshape(1, 1);
                    matTrainingImagesAsFlattenedFloats.push_back(matImageFlattenedFloat);
                }
            }
        }
       //Here should go FileStorage stuff.
    }   
}

提前致谢。
附:使用 OpenCV_310 + Java(不是 JavaCV)

【问题讨论】:

    标签: java c++ opencv


    【解决方案1】:

    好吧,我已经自己解决了。 很脏,我猜,但就是这样。如果您知道如何对我的代码进行良好的改进,我会很高兴阅读您的 cmets。
    1)我的第一个问题是关于将 int 放入 Mat (用于进一步制作 *.xml)。我避免了这种方法,并决定将 int(实际上是 Integer)放入 List。

     Scanner keyboard = new Scanner(System.in);
     String input = keyboard.nextLine();
     int intChar = (int)input.charAt(0);
     List<Integer> matClassificationInts = new ArrayList<Integer>();
     if (Arrays.binarySearch(intValidChars, intChar) >=0) {
        matClassificationInts.add(new Integer(intChar));
        ......
     }
     String dataImages = "";
     for (Integer i : matClassificationInts) {
         dataImages += i + " ";
     }
    

    我可以制作字符串(例如“49 48”字符“1 0”整数)以将其保存在 *.xml 中(参见下一段)。
    2) 第二个问题是关于从 Mat 中提取数据并将其存储在 *.xml 中。好吧,通过 C++,我可以通过 FileStorage 来实现:

    cv::FileStorage fsClassifications("classifications.xml", cv::FileStorage::WRITE);
    fsClassifications << "classifications" << matClassificationInts;
    fsClassifications.release();
    

    但是 Java OpenCV 没有这样的功能,所以我循环遍历二维数组(Mat.rows() 和 Mat.cols())并通过 get() 方法提取所需的数据(Mat.get(row, col) -给出双精度数组,数组长度 = 1):

    String dataClassifications = "";
    for (int i = 0; i < matTrainingImagesAsFlattenedFloats.rows(); i++) {
        for (int j = 0; j < matTrainingImagesAsFlattenedFloats.cols(); j++) {
            double[] temp = matTrainingImagesAsFlattenedFloats.get(i, j);
            dataClassifications += temp[0] + " ";
        }
        dataClassifications += "\n";
    }
    

    现在,关于将数据保存到 *.xml:
    我刚刚使用了 javafx.xmlorg.wc3.dom 库。
    制作了两个用于返回 DOM 节点的函数:

    private static Node getMatXML(Document doc, String option_id, String type_id, String rows, String cols, String dt, String data) {
        Element elem = doc.createElement(option_id);
        elem.setAttribute("type_id", type_id);
        elem.appendChild(getMatXMLElement(doc,"rows", rows));
        elem.appendChild(getMatXMLElement(doc, "cols", cols));
        elem.appendChild(getMatXMLElement(doc, "dt", dt));
        elem.appendChild(getMatXMLElement(doc, "data", data));
        return elem;
    }
    
    private static Node getMatXMLElement(Document doc, String name, String value) {
        Element node = doc.createElement(name);
        node.appendChild(doc.createTextNode(value));
        return node;
    }
    

    并使用这些函数来创建 *.xml:
    分类.xml:

        DocumentBuilderFactory icFactory_images = DocumentBuilderFactory.newInstance();
        DocumentBuilder icBuilder_images;
        try {
            icBuilder_images = icFactory_images.newDocumentBuilder();
            Document doc = icBuilder_images.newDocument();
            Element mainRootElement = doc.createElement("opencv_storage");
            doc.appendChild(mainRootElement);
            mainRootElement.appendChild(getMatXML(doc, "classifications", "opencv-matrix", rowsImages, colsImages, "i", dataImages));
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
            DOMSource source = new DOMSource(doc);
            String filename = "classifications.xml";
            File file = new File(filename);
            StreamResult console = new StreamResult(file); //(System.out)
            transformer.transform(source, console);
        } catch (Exception e) {
            e.printStackTrace();
        }
    

    Images.xml:

        DocumentBuilderFactory icFactory_classifications = DocumentBuilderFactory.newInstance();
        DocumentBuilder icBuilder_classifications;
        try {
            icBuilder_classifications = icFactory_classifications.newDocumentBuilder();
            Document doc = icBuilder_classifications.newDocument();
            Element mainRootElement = doc.createElement("opencv_storage");
            doc.appendChild(mainRootElement);
            mainRootElement.appendChild(getMatXML(doc, "images", "opencv-matrix", rowsClassifications, colsClassifications, "f", dataClassifications));
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
            DOMSource source = new DOMSource(doc);
            String filename = "images.xml";
            File file = new File(filename);
            StreamResult console = new StreamResult(file); //(System.out)
            transformer.transform(source, console);
        } catch (Exception e) {
            e.printStackTrace();
        }
    

    例如,生成的分类文件是:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <opencv_storage>
    <classifications type_id="opencv-matrix">
    <rows>2</rows>
    <cols>1</cols>
    <dt>i</dt>
    <data>49 48 </data>
    </classifications>
    </opencv_storage>
    

    我为这张照片做了测试:

    通过 GenData.cpp(参见相关链接 - 第 1 行)和我的 Java 代码(完整代码见下文)。两个程序都给了我相同的结果:
    对于 Java OpenCV Imshow 实现,您可以查看 this link(不是我的)。

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    import java.util.Scanner;
    import org.opencv.core.Core;
    import static org.opencv.core.CvType.CV_32FC1;
    import org.opencv.core.Mat;
    import org.opencv.core.MatOfInt4;
    import org.opencv.core.MatOfPoint;
    import org.opencv.core.Rect;
    import org.opencv.core.Scalar;
    import org.opencv.core.Size;
    import org.opencv.imgcodecs.Imgcodecs;
    import org.opencv.imgproc.Imgproc;
    import static org.opencv.imgproc.Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C;
    import static org.opencv.imgproc.Imgproc.CHAIN_APPROX_SIMPLE;
    import static org.opencv.imgproc.Imgproc.RETR_EXTERNAL;
    import static org.opencv.imgproc.Imgproc.THRESH_BINARY_INV;
    
    //XML - write.
    import javax.xml.parsers.DocumentBuilder;
    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 org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    
    public class genData {
    
    
        private static final int 
                MIN_CONTOUR_AREA = 100,
                RESIZED_IMAGE_WIDTH = 20,
                RESIZED_IMAGE_HEIGHT = 30;
    
        public static void main(String[] args) throws IOException {
            System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 
            Scanner keyboard = new Scanner(System.in);
    
            Mat imgTrainingNumbers;
            Mat imgGrayscale = new Mat();
            Mat imgBlurred = new Mat();
            Mat imgThresh = new Mat();
            Mat imgThreshCopy = new Mat();
    
            ArrayList<MatOfPoint> ptContours = new ArrayList<MatOfPoint>();
            MatOfInt4 v4iHierarchy = new MatOfInt4();
    
            List<Integer> matClassificationInts = new ArrayList<Integer>();
    
            Mat matTrainingImagesAsFlattenedFloats = new Mat();
    
            int[] intValidChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'A', 'B', 'C', 'E', 'H',
            'K', 'M', 'O', 'P', 'T',
            'X', 'Y'};
            Arrays.sort(intValidChars);
    
            imgTrainingNumbers = Imgcodecs.imread("01.png");
    
            if (imgTrainingNumbers.empty()) {
                System.out.println("Error: file is not found");
                return;
            }
    
            Imgproc.cvtColor(imgTrainingNumbers, imgGrayscale, Imgproc.COLOR_BGR2GRAY);
            Imgproc.GaussianBlur(imgGrayscale, imgBlurred, new Size(5, 5), 0);
            Imgproc.adaptiveThreshold(imgBlurred, imgThresh, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 11, 2);
    
            Imshow im = new Imshow("imgThresh");
            im.showImage(imgThresh);
            imgThreshCopy = imgThresh.clone();
    
            Imgproc.findContours(imgThreshCopy, ptContours, v4iHierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
    
    
            for (int i = 0; i < ptContours.size(); i++) {
                if (Imgproc.contourArea(ptContours.get(i)) > MIN_CONTOUR_AREA) {
                    Rect boundingRect = Imgproc.boundingRect(ptContours.get(i));
                    Imgproc.rectangle(imgTrainingNumbers, boundingRect.tl(), boundingRect.br(), new Scalar(0, 0, 255), 2);
                    Mat matROI = imgThresh.submat(boundingRect.y, boundingRect.y + boundingRect.height, boundingRect.x, boundingRect.x + boundingRect.width);
                    Mat matROIResized = new Mat();
                    Imgproc.resize(matROI, matROIResized, new Size(RESIZED_IMAGE_WIDTH, RESIZED_IMAGE_HEIGHT));
                    im.showImage(matROI);
                    im.showImage(matROIResized);
                    im.showImage(imgTrainingNumbers);
                    String input = keyboard.nextLine();
                    int intChar = (int)input.charAt(0);
                    if (Arrays.binarySearch(intValidChars, intChar) >=0) {
                        matClassificationInts.add(new Integer(intChar));
                        Mat matImageFloat = new Mat();
                        matROIResized.convertTo(matImageFloat, CV_32FC1);
                        Mat matImageFlattenedFloat = matImageFloat.reshape(1, 1);
                        matTrainingImagesAsFlattenedFloats.push_back(matImageFlattenedFloat);
                    }
                }
            }
    
            String dataImages = "";
            for (Integer i : matClassificationInts) {
                dataImages += i + " ";
            }
    
            String dataClassifications = "";
            for (int i = 0; i < matTrainingImagesAsFlattenedFloats.rows(); i++) {
                for (int j = 0; j < matTrainingImagesAsFlattenedFloats.cols(); j++) {
                    double[] temp = matTrainingImagesAsFlattenedFloats.get(i, j);
                    dataClassifications += temp[0] + " ";
                }
                dataClassifications += "\n";
            }
    
            String rowsImages = String.valueOf(matClassificationInts.size());
            String colsImages = "1";
            String rowsClassifications = String.valueOf(matTrainingImagesAsFlattenedFloats.rows());
            String colsClassifications = String.valueOf(matTrainingImagesAsFlattenedFloats.cols());
    
            DocumentBuilderFactory icFactory_images = DocumentBuilderFactory.newInstance();
            DocumentBuilder icBuilder_images;
            try {
                icBuilder_images = icFactory_images.newDocumentBuilder();
                Document doc = icBuilder_images.newDocument();
                Element mainRootElement = doc.createElement("opencv_storage");
                doc.appendChild(mainRootElement);
                mainRootElement.appendChild(getMatXML(doc, "classifications", "opencv-matrix", rowsImages, colsImages, "i", dataImages));
                Transformer transformer = TransformerFactory.newInstance().newTransformer();
                transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
                DOMSource source = new DOMSource(doc);
                String filename = "classifications.xml";
                File file = new File(filename);
                StreamResult console = new StreamResult(file); //(System.out)
                transformer.transform(source, console);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            DocumentBuilderFactory icFactory_classifications = DocumentBuilderFactory.newInstance();
            DocumentBuilder icBuilder_classifications;
            try {
                icBuilder_classifications = icFactory_classifications.newDocumentBuilder();
                Document doc = icBuilder_classifications.newDocument();
                Element mainRootElement = doc.createElement("opencv_storage");
                doc.appendChild(mainRootElement);
                mainRootElement.appendChild(getMatXML(doc, "images", "opencv-matrix", rowsClassifications, colsClassifications, "f", dataClassifications));
                Transformer transformer = TransformerFactory.newInstance().newTransformer();
                transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
                DOMSource source = new DOMSource(doc);
                String filename = "images.xml";
                File file = new File(filename);
                StreamResult console = new StreamResult(file); //(System.out)
                transformer.transform(source, console);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("Finished.");
            System.exit(0);
        }   
    
        private static Node getMatXML(Document doc, String option_id, String type_id, String rows, String cols, String dt, String data) {
            Element elem = doc.createElement(option_id);
            elem.setAttribute("type_id", type_id);
            elem.appendChild(getMatXMLElement(doc,"rows", rows));
            elem.appendChild(getMatXMLElement(doc, "cols", cols));
            elem.appendChild(getMatXMLElement(doc, "dt", dt));
            elem.appendChild(getMatXMLElement(doc, "data", data));
            return elem;
        }
    
        private static Node getMatXMLElement(Document doc, String name, String value) {
            Element node = doc.createElement(name);
            node.appendChild(doc.createTextNode(value));
            return node;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-06-23
      • 2012-03-28
      • 1970-01-01
      • 2014-07-03
      • 1970-01-01
      • 1970-01-01
      • 2013-10-08
      • 1970-01-01
      • 2014-02-13
      相关资源
      最近更新 更多