微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

OpenCVSharp - 比较图像 - Sift/Surf/Hash/Orb

如何解决OpenCVSharp - 比较图像 - Sift/Surf/Hash/Orb

我知道这个话题在互联网上被广泛讨论,但我找不到我的问题的答案......

所以我的最终目标是提取图像的一部分并将其与“模板”进行比较。 我已经提取并裁剪了图像的一部分,所以这不是问题。

我遇到的问题是试图将它与它的模板进行比较。模板最初是 SVG,所以我将其转换为 JPG 并删除了 alpha 通道。

模板:

Image Template

实际图像取自网络摄像头,因此它是彩色的,但我可以轻松地设置阈值以仅保留黑色/白色。

网络摄像头图像:

enter image description here

具有阈值的网络摄像头图像

enter image description here

所以我尝试了 3 种方法

1. SIFT algorithm. 
 

private void MatchBySift(Mat src1,Mat src2)

        {

            var gray1 = new Mat();
            var gray2 = new Mat();

            Cv2.CvtColor(src1,gray1,ColorConversionCodes.BGR2GRAY);
            Cv2.CvtColor(src2,gray2,ColorConversionCodes.BGR2GRAY);

            var sift = SIFT.Create();

            // Detect the keypoints and generate their descriptors using SIFT
            KeyPoint[] keypoints1,keypoints2;
            var descriptors1 = new Mat();   //<float>
            var descriptors2 = new Mat();   //<float>
            sift.DetectAndCompute(gray1,null,out keypoints1,descriptors1);
            sift.DetectAndCompute(gray2,out keypoints2,descriptors2);

            // Match descriptor vectors
            var bfMatcher = new BFMatcher(normTypes.L2,false);
            var flannMatcher = new FlannBasedMatcher();
            DMatch[] bfMatches;
            DMatch[] flannMatches;
            try
            {
                bfMatches = bfMatcher.Match(descriptors1,descriptors2);
                flannMatches = flannMatcher.Match(descriptors1,descriptors2);
            }
            catch
            {
                bfMatches = new DMatch[0];
                flannMatches = new DMatch[0];
            }
            

            // Draw matches
            var bfView = new Mat();
            Cv2.DrawMatches(gray1,keypoints1,keypoints2,bfMatches,bfView);
            var flannView = new Mat();
            Cv2.DrawMatches(gray1,flannMatches,flannView);
            Console.WriteLine("BF Matches: " + bfMatches.Length);
            Console.WriteLine("Flann Matches: " + flannMatches.Length);
            
            using (new Window("SIFT matching (by BFMather)",bfView))
            using (new Window("SIFT matching (by FlannBasedMatcher)",flannView))
            {
                Cv2.WaitKey();
            }
            
        }

2. SURF Algorithm

    private void MatchBySurf(Mat src1,Mat src2)
            {
                var gray1 = new Mat();
                var gray2 = new Mat();
    
                Cv2.CvtColor(src1,ColorConversionCodes.BGR2GRAY);
                Cv2.CvtColor(src2,ColorConversionCodes.BGR2GRAY);
    
                var surf = SURF.Create(200,4,2,true);
    
                // Detect the keypoints and generate their descriptors using SURF
                KeyPoint[] keypoints1,keypoints2;
                var descriptors1 = new Mat();   //<float>
                var descriptors2 = new Mat();   //<float>
                surf.DetectAndCompute(gray1,descriptors1);
                surf.DetectAndCompute(gray2,descriptors2);
    
                // Match descriptor vectors 
                var bfMatcher = new BFMatcher(normTypes.L2,false);
                var flannMatcher = new FlannBasedMatcher();
                DMatch[] bfMatches;
                DMatch[] flannMatches;
                try
                {
                    bfMatches = bfMatcher.Match(descriptors1,descriptors2);
                    flannMatches = flannMatcher.Match(descriptors1,descriptors2);
                }
                catch
                {
                    bfMatches = new DMatch[0];
                    flannMatches = new DMatch[0];
                }
    
                // Draw matches
                var bfView = new Mat();
                Cv2.DrawMatches(gray1,bfView);
                var flannView = new Mat();
                Cv2.DrawMatches(gray1,flannView);
    
                Console.WriteLine("BF Matches: " + bfMatches.Length);
                Console.WriteLine("Flann Matches: " + flannMatches.Length);
                /*
                using (new Window("SURF matching (by BFMather)",bfView))
                using (new Window("SURF matching (by FlannBasedMatcher)",flannView))
                {
                    Cv2.WaitKey();
                }
                */
            }

3. Hash comparison

    private void MatchByHash(Mat src1,Mat src2)
            {
                Bitmap bit1 = BitmapConverter.ToBitmap(src1);
                Bitmap bit2 = BitmapConverter.ToBitmap(src2);
                List<bool> hash1 = GetHash(bit1);
                List<bool> hash2 = GetHash(bit2);
    
                int equalElements = hash1.Zip(hash2,(i,j) => i == j).Count(eq => eq);
    
                Console.WriteLine("Match by Hash: " + equalElements);
            }
    
            public List<bool> GetHash(Bitmap bmpSource)
            {
                List<bool> lResult = new List<bool>();
                //create new image with 16x16 pixel
                Bitmap bmpMin = new Bitmap(bmpSource,new System.Drawing.Size(16,16));
                for (int j = 0; j < bmpMin.Height; j++)
                {
                    for (int i = 0; i < bmpMin.Width; i++)
                    {
                        //reduce colors to true / false                
                        lResult.Add(bmpMin.GetPixel(i,j).GetBrightness() < 0.5f);
                    }
                }
                return lResult;
            }

为什么我对结果不满意

  1. 筛选和冲浪

比较上面的图像时,我根据匹配的数量获得了一定的相似性。问题是当我使用不同的 template image 时,我总是得到相同的数字......我认为这是因为没有颜色,但我需要在这里澄清

  1. 哈希

在其他“模板”上使用时,我得到了更高的结果!这基本上消除了这种方法,除非它可以以某种方式改进......

我也听说过 ORB 算法,但我还没有尝试实现它。这对我来说会更好吗?

如果我可以尝试任何其他方法,请指出正确的方向!

谢谢

解决方法

主要是注册标志和模板。由于您的图像是准二进制的并且仅包含徽标,因此您可以依赖矩的计算。您将为二值化图像和二值化模板计算它们。

黑色像素的零阶矩是面积。面积比的平方根为您提供比例因子。

Y 时刻的一阶 X 为您提供参考点(质心)的位置,这在两者中都是相同的。

然后居中的二阶矩 (X²,Y²,XY) 将为您提供两个主要方向(通过计算惯性张量的特征向量),并由此得出徽标和模板之间的旋转角度。

https://www.ae.msstate.edu/vlsm/shape/area_moments_of_inertia/papmi.htm

现在您可以重新缩放、旋转和平移徽标或模板以叠加它们。您只需计算匹配颜色的像素即可获得比较分数。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。