最近,我一直在开发一个小型的副项目,该项目需要能够在另一个图像中找到子图像的X和Y坐标。 图像可能具有不同的分辨率,但总体而言,图像分辨率将相似且颜色应相同。 我已经研究过OpenCV,但似乎OpenCV只返回一个匹配项。 我需要在超级图像中找到子图像的所有出现/实例。 我已经有所有要搜索的子图像,因此只需要一种方法即可在超图像中找到子图像的坐标。

这是我的意思的示例:

如果我们有red_circle.png

红圈子图像

shapes.png

塑造超级图像

我需要获取各种形状( shapes.png ;超图像)图片中所有红色圆圈( red_circle.png ;子图像)的X和Y坐标。

理想情况下,我希望能够执行以下操作:

/* code to read in red_cirlce.png and shapes.png as BufferedImages */
ArrayList<Point> instancesOfRedCircle = new ArrayList<>();
findAllSubimageInstances( shapesObj, // Super-Image
                          redCircleObj, // Subimage
                          instancesOfRedCircle // ArrayList to put points in
                        );

是否有人知道执行此操作的方法(例如,库,函数等)?

#1楼 票数:12 已采纳

我无法入睡。

在此处输入图片说明

我已经用Java用tuorial编写了代码,并围绕它构建了一些gui。

package opencv.test;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;

import javax.imageio.ImageIO;

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.MatOfDMatch;
import org.opencv.core.MatOfKeyPoint;
import org.opencv.core.Scalar;
import org.opencv.features2d.DMatch;
import org.opencv.features2d.DescriptorExtractor;
import org.opencv.features2d.DescriptorMatcher;
import org.opencv.features2d.FeatureDetector;
import org.opencv.features2d.Features2d;
import org.opencv.highgui.Highgui;

public class MatchDetection {

    public static BufferedImage detectMatches(File file, File file2) {

        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        Mat img_1 = Highgui.imread(file.getAbsolutePath(), Highgui.CV_LOAD_IMAGE_GRAYSCALE);
        Mat img_2 = Highgui.imread(file2.getAbsolutePath(), Highgui.CV_LOAD_IMAGE_GRAYSCALE);

        if (img_1.empty() || img_2.empty()) {
            System.out.println(" --(!) Error reading images ");
            return null;
        }

        // -- Step 1: Detect the keypoints using SURF Detector
        //I am not sure where to use it
        int minHessian = 400;

        FeatureDetector detector = FeatureDetector.create(FeatureDetector.SURF);

        MatOfKeyPoint keypoints_1 = new MatOfKeyPoint();
        MatOfKeyPoint keypoints_2 = new MatOfKeyPoint();

        detector.detect(img_1, keypoints_1);
        detector.detect(img_2, keypoints_2);

        // -- Step 2: Calculate descriptors (feature vectors)
        DescriptorExtractor extractor = DescriptorExtractor
                .create(DescriptorExtractor.SURF);

        Mat descriptors_1 = new Mat();
        Mat descriptors_2 = new Mat();

        extractor.compute(img_1, keypoints_1, descriptors_1);
        extractor.compute(img_2, keypoints_2, descriptors_2);

        // -- Step 3: Matching descriptor vectors using FLANN matcher
        DescriptorMatcher matcher = DescriptorMatcher
                .create(DescriptorExtractor.SURF);
        MatOfDMatch matches = new MatOfDMatch();
        matcher.match(descriptors_1, descriptors_2, matches);
        DMatch[] matchesArr = matches.toArray();

        double max_dist = 0;
        double min_dist = 100;

        // -- Quick calculation of max and min distances between keypoints
        for (int i = 0; i < matchesArr.length; i++) {
            double dist = matchesArr[i].distance;
            if (dist < min_dist)
                min_dist = dist;
            if (dist > max_dist)
                max_dist = dist;
        }

        System.out.printf("-- Max dist : %f \n", max_dist);
        System.out.printf("-- Min dist : %f \n", min_dist);

        // -- Draw only "good" matches (i.e. whose distance is less than
        // 2*min_dist,
        // -- or a small arbitary value ( 0.02 ) in the event that min_dist is
        // very
        // -- small)
        // -- PS.- radiusMatch can also be used here.
        MatOfDMatch good_matches = new MatOfDMatch();

        for (int i = 0; i < matchesArr.length; i++) {
            if (matchesArr[i].distance <= Math.max(2 * min_dist, 0.02)) {
                good_matches.push_back(matches.row(i));
            }
        }

        // -- Draw only "good" matches
        Mat img_matches = new Mat();
        Features2d.drawMatches(img_1, keypoints_1, img_2, keypoints_2,
                good_matches, img_matches);//, Scalar.all(-1), Scalar.all(-1),
                //null, Features2d.NOT_DRAW_SINGLE_POINTS);

        // ----Here i had to Patch around a little----
        MatOfByte matOfByte = new MatOfByte();

        Highgui.imencode(".jpg", img_matches, matOfByte);

        byte[] byteArray = matOfByte.toArray();
        BufferedImage bufImage = null;
        try {

            InputStream in = new ByteArrayInputStream(byteArray);
            bufImage = ImageIO.read(in);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        for (int i = 0; i < (int) good_matches.rows(); i++) {
            System.out.printf(
                    "-- Good Match [%d] Keypoint 1: %d  -- Keypoint 2: %d  \n",
                    i, good_matches.toArray()[i].queryIdx,
                    good_matches.toArray()[i].trainIdx);
        }

        return bufImage;

    }
}

和GUI

package opencv.test;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;

public class OpenCVMyGui {

    private JFrame frame;
    ImageResultPanel panel_bot;
    ImageChoosePanel panel_left;
    ImageChoosePanel panel_right;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    OpenCVMyGui window = new OpenCVMyGui();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public OpenCVMyGui() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        GridBagLayout gridBagLayout = new GridBagLayout();
        gridBagLayout.columnWidths = new int[]{0, 0, 0};
        gridBagLayout.rowHeights = new int[]{0, 0, 0};
        gridBagLayout.columnWeights = new double[]{1.0, 1.0, Double.MIN_VALUE};
        gridBagLayout.rowWeights = new double[]{1.0, 1.0, Double.MIN_VALUE};
        frame.getContentPane().setLayout(gridBagLayout);

        panel_left = new ImageChoosePanel();
        GridBagConstraints gbc_panel_2 = new GridBagConstraints();
        gbc_panel_2.insets = new Insets(0, 0, 5, 5);
        gbc_panel_2.fill = GridBagConstraints.BOTH;
        gbc_panel_2.gridx = 0;
        gbc_panel_2.gridy = 0;
        frame.getContentPane().add(panel_left, gbc_panel_2);

        panel_right = new ImageChoosePanel();
        GridBagConstraints gbc_panel_1 = new GridBagConstraints();
        gbc_panel_1.insets = new Insets(0, 0, 5, 0);
        gbc_panel_1.fill = GridBagConstraints.BOTH;
        gbc_panel_1.gridx = 1;
        gbc_panel_1.gridy = 0;
        frame.getContentPane().add(panel_right, gbc_panel_1);

        panel_bot = new ImageResultPanel(this);
        GridBagConstraints gbc_panel = new GridBagConstraints();
        gbc_panel.gridwidth = 2;
        gbc_panel.fill = GridBagConstraints.BOTH;
        gbc_panel.gridx = 0;
        gbc_panel.gridy = 1;
        frame.getContentPane().add(panel_bot, gbc_panel);
    }

    private class ImageChoosePanel extends JPanel {

        /**
         * 
         */
        private static final long serialVersionUID = 2207576827793103205L;
        public BufferedImage image;
        public File file;

        public ImageChoosePanel() {
            setFocusable(true);
            addMouseListener(new MouseListener() {

                @Override
                public void mouseReleased(MouseEvent e) {
                }

                @Override
                public void mousePressed(MouseEvent e) {
                }

                @Override
                public void mouseExited(MouseEvent e) {
                }

                @Override
                public void mouseEntered(MouseEvent e) {
                }

                @Override
                public void mouseClicked(MouseEvent e) {
                    JFileChooser chooser = new JFileChooser();
                    chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
                    chooser.setFileFilter(new FileNameExtensionFilter("Images",
                            "jpg", "png")); // maybe more? dont know what OpenCV
                                            // likes
                    chooser.showOpenDialog(ImageChoosePanel.this);
                    ImageChoosePanel icp = ((ImageChoosePanel) e.getSource());
                    icp.file = chooser.getSelectedFile();
                    try {
                        image = ImageIO.read(icp.file);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            });
        }

        @Override
        public void paint(Graphics arg0) {

            if (image != null) {
                arg0.drawImage(image, 0, 0, null);
            } else{ 
                arg0.fillRect(0, 0, getWidth(), getHeight());
            }
        }
    }

    private class ImageResultPanel extends JPanel {

        /**
         * 
         */
        private static final long serialVersionUID = 8948107638933808175L;
        public BufferedImage image;
        OpenCVMyGui gui;

        public ImageResultPanel(OpenCVMyGui gui) {
            this.gui = gui;
            setFocusable(true);
            addMouseListener(new MouseListener() {

                @Override
                public void mouseReleased(MouseEvent arg0) {
                }

                @Override
                public void mousePressed(MouseEvent arg0) {
                }

                @Override
                public void mouseExited(MouseEvent arg0) {
                }

                @Override
                public void mouseEntered(MouseEvent arg0) {
                }

                @Override
                public void mouseClicked(MouseEvent arg0) {
                    try {
                        OpenCVMyGui gui = ((ImageResultPanel) arg0.getSource()).gui;
                        image = MatchDetection.detectMatches(
                                gui.panel_right.file, gui.panel_left.file);
                    } catch (Exception e2) {
                        e2.printStackTrace();
                    }
                }
            });
        }

        @Override
        public void paint(Graphics arg0) {
            if (image != null) {
                arg0.drawImage(image, 0, 0, null);
            }else{
                arg0.fillRect(0, 0, getWidth(), getHeight());
            }
        }
    }

}

您应该仔细研究算法...但是结果atm应该可以帮助您实现目标。

我可能会再读一遍。 明天。

#2楼 票数:2

看一下本教程:

http://docs.opencv.org/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.html#feature-flann-matcher

它的C ++代码,但是您可以猜测它是如何工作的,而OpenCV的Java Api非常接近C ++ Api。

希望对您有所帮助。

如果您认为这超出了目标范围,则可以尝试遍历pixelx。 但是,使用不同的大小会很复杂。

  ask by Spencer D translate from so

未解决问题?本站智能推荐:

2回复

使用javacv中的匹配模板在图像的特定区域查找图像

我试图在另一个特定区域内查找图像的位置。 我正在使用javacv来解决此问题。 但是我的代码在执行cvMatchTemplate函数时给出错误。 我想我想念使用cvSetImageROI 。 这就是我的使用方式: 这是错误: 有帮助吗?
2回复

Open CV中的2D子图像检测

对于以下问题,OpenCV使用哪种最明智的算法或算法组合: 我有一组小的2D图像。 我想在更大的图像中检测这些子图像的位置。 子图像通常约为32x32像素,较大的图像约为400x400。 子图像并不总是正方形,因此包含alpha通道。 可选地 - 较大的图像可
2回复

如何检测一个图像是否在另一个图像中?

我试图检测一个图像是否与另一个图像 100% 匹配,然后将一个变量设置为True如果是)。 但是,除了给出此代码的一个特定线程之外,我阅读的所有内容几乎没有结果。 但是,这会打开一个输出,并执行我不想做的事情。 我想要做的就是检测图像是否在图像中,如果是,则将其打印到控制台。 在我的特殊情况下,
1回复

如何使用OPENCV从图像中检测特定号码?

我住在土耳其,在土耳其,电视广告正在做一些倒计时,告诉我们电视节目或电影播放还剩多少分钟。 我想做的是赶上00:59秒,或者只是计数器上的第二个“ 0”。 算法必须了解“ 0”是“ 0”,而不是其他任何数字。 之后,我尝试了将模板与模板图像进行匹配,但是它也检测到错误的数字。
1回复

模板匹配矩形的简单二进制图像

我有一组由二进制矩形组成的训练图像。 我需要编写一个程序来获取另一个二进制图像(带有噪声,比例,旋转和矩形位置的轻微偏移),并在训练集中找到最接近的匹配图像 例如输入图像: 训练有素的图像:应与此匹配 训练有素的图像:不应该与此搭配 据我所知,有3种方
1回复

如何找到warpPerspective的变换矩阵以将旋转的图像带到标准化位置?

我需要处理从扫描仪获得的一些信息。 问题是偶尔旋转的图像。 我决定在照片上添加一些特殊对象,以便能够使用技术Features2D + Homography来找到该对象。 我想在找到特殊物体后,我可以将图像旋转回原来的位置(使用warpPerspective?)。 这是一个例子: 旋转
4回复

图像匹配,仿射变形

我的问题在这里显示: 问题陈述 。 我有一个模板图像,我必须在相机图像中检测。 在检测到之后,我必须通过使用仿射变换来标准化相机图像。 我的工作目标是识别十字架。 我尝试使用SURF功能进行图像归一化步骤,但模板图像非常规则,不适合SURF匹配。 有什么想法可以做到这一点? 也许某种
2回复

车牌图像匹配

我想匹配两个车牌图像,下面给出了示例图像 这里这两个车牌属于同一辆车,因此它们应该匹配。 在这些图像中可能存在缩放和轻微旋转,如示例中所示,也只能看到一部分原始图像。 如果车牌属于不同的车辆算法应该说是不同的。 哪个是最佳的算法?