﻿
{"id":6886,"date":"2017-09-03T01:29:25","date_gmt":"2017-09-03T01:29:25","guid":{"rendered":"http:\/\/www.gencayyildiz.com\/blog\/?p=6886"},"modified":"2017-09-03T01:29:25","modified_gmt":"2017-09-03T01:29:25","slug":"emgu-cv-surf-algoritmasi-ile-nesne-takibi","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/emgu-cv-surf-algoritmasi-ile-nesne-takibi\/","title":{"rendered":"Emgu CV &#8211; SURF Algoritmas\u0131 \u0130le Nesne Takibi"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>\u015euana kadar g\u00f6r\u00fcnt\u00fc i\u015fleme \u00fczerine yapm\u0131\u015f oldu\u011fumuz t\u00fcm \u00e7al\u0131\u015fmalar neticesinde bir \u00e7ok Image Processing algoritmas\u0131n\u0131n mevcut oldu\u011fundan bahsetmi\u015f bulunmaktay\u0131z. Bu algoritmalar aras\u0131nda; g\u00f6r\u00fcnt\u00fc \u00fczerinde bir nesneyi alg\u0131lamam\u0131z\u0131 sa\u011flayan ve bu i\u015flemi yaparken boyut, renk vs. gibi \u00f6zelliklerinden ba\u011f\u0131ms\u0131z bir \u015fekilde \u00e7al\u0131\u015fan SURF algoritmas\u0131n\u0131 ele alaca\u011f\u0131z.<\/p>\n<p>SURF algoritmas\u0131, yukar\u0131da da ifade etmeye \u00e7al\u0131\u015ft\u0131\u011f\u0131m gibi \u00f6l\u00e7ekleme ve rotasyondan ba\u011f\u0131ms\u0131zd\u0131r. Bu y\u00fczden de\u011fi\u015fik bak\u0131\u015f a\u00e7\u0131lar\u0131na ve \u0131\u015f\u0131nsal a\u00e7\u0131lara kar\u015f\u0131 gayet diren\u00e7li olmas\u0131ndan dolay\u0131 nesneyi alg\u0131lamada do\u011fruluk oran\u0131 olduk\u00e7a y\u00fckse ve performansl\u0131d\u0131r.<\/p>\n<p>Bizler bu makalemizde SURF algoritmas\u0131n\u0131 kullanaca\u011f\u0131m\u0131z s\u0131n\u0131f yap\u0131m\u0131z\u0131 in\u015fa edece\u011fiz ve \u00e7al\u0131\u015fmam\u0131z\u0131 bir form \u00fczerinde \u00f6rneklendirece\u011fiz. E\u011fer ki, sizlerde bu makaleyle birlikte paralel icraatte bulunmay\u0131 d\u00fc\u015f\u00fcn\u00fcyorsan\u0131z hali haz\u0131rda bir Windows Forms projesi a\u00e7\u0131n\u0131z ve form \u00fczerinde bir adet PictureBox nesnesi ile projeye gerekli EmguCV entegrasyonunu sa\u011flayarak s\u00fcrece e\u015flik etmek i\u00e7in haz\u0131r bekleyiniz&#8230;<\/p>\n<p>Evet&#8230;<\/p>\n<p>\u015eimdi ba\u015flayabiliriz&#8230;<\/p>\n<p>\u00d6ncelikle SURF algoritmam\u0131z\u0131 bar\u0131nd\u0131ran s\u0131n\u0131f\u0131m\u0131z\u0131 in\u015fa edelim.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    static class SURFAlgoritmasi\r\n    {\r\n        public static Image&lt;Bgr, Byte&gt; Draw(Image&lt;Gray, Byte&gt; modelImage, Image&lt;Gray, byte&gt; observedImage)\r\n        {\r\n            HomographyMatrix homography = null;\r\n            SURFDetector surfCPU = new SURFDetector(500, false);\r\n            VectorOfKeyPoint modelKeyPoints;\r\n            VectorOfKeyPoint observedKeyPoints;\r\n            Matrix&lt;int&gt; indices;\r\n            Matrix&lt;byte&gt; mask;\r\n            int k = 2;\r\n            double uniquenessThreshold = 0.8;\r\n            if (GpuInvoke.HasCuda)\r\n            {\r\n                GpuSURFDetector surfGPU = new GpuSURFDetector(surfCPU.SURFParams, 0.01f);\r\n                GpuImage&lt;Gray, Byte&gt; gpuModelImage = new GpuImage&lt;Gray, byte&gt;(modelImage);\r\n                \/\/extract features from the object image\r\n                GpuMat&lt;float&gt; gpuModelKeyPoints = surfGPU.DetectKeyPointsRaw(gpuModelImage, null);\r\n                GpuMat&lt;float&gt; gpuModelDescriptors = surfGPU.ComputeDescriptorsRaw(gpuModelImage, null, gpuModelKeyPoints);\r\n                GpuBruteForceMatcher&lt;float&gt; matcher = new GpuBruteForceMatcher&lt;float&gt;(DistanceType.L2);\r\n                modelKeyPoints = new VectorOfKeyPoint();\r\n                surfGPU.DownloadKeypoints(gpuModelKeyPoints, modelKeyPoints);\r\n                GpuImage&lt;Gray, Byte&gt; gpuObservedImage = new GpuImage&lt;Gray, byte&gt;(observedImage);\r\n                GpuMat&lt;float&gt; gpuObservedKeyPoints = surfGPU.DetectKeyPointsRaw(gpuObservedImage, null);\r\n                GpuMat&lt;float&gt; gpuObservedDescriptors = surfGPU.ComputeDescriptorsRaw(gpuObservedImage, null, gpuObservedKeyPoints);\r\n                GpuMat&lt;int&gt; gpuMatchIndices = new GpuMat&lt;int&gt;(gpuObservedDescriptors.Size.Height, k, 1, true);\r\n                GpuMat&lt;float&gt; gpuMatchDist = new GpuMat&lt;float&gt;(gpuObservedDescriptors.Size.Height, k, 1, true);\r\n                GpuMat&lt;Byte&gt; gpuMask = new GpuMat&lt;byte&gt;(gpuMatchIndices.Size.Height, 1, 1);\r\n                Stream stream = new Stream();\r\n                matcher.KnnMatchSingle(gpuObservedDescriptors, gpuModelDescriptors, gpuMatchIndices, gpuMatchDist, k, null, stream);\r\n                indices = new Matrix&lt;int&gt;(gpuMatchIndices.Size);\r\n                mask = new Matrix&lt;byte&gt;(gpuMask.Size);\r\n                GpuMat&lt;float&gt; col0 = gpuMatchDist.Col(0);\r\n                GpuMat&lt;float&gt; col1 = gpuMatchDist.Col(1);\r\n                GpuInvoke.Multiply(col1, new MCvScalar(uniquenessThreshold), col1, stream);\r\n                GpuInvoke.Compare(col0, col1, gpuMask, CMP_TYPE.CV_CMP_LE, stream);\r\n                observedKeyPoints = new VectorOfKeyPoint();\r\n                surfGPU.DownloadKeypoints(gpuObservedKeyPoints, observedKeyPoints);\r\n                stream.WaitForCompletion();\r\n                gpuMask.Download(mask);\r\n                gpuMatchIndices.Download(indices);\r\n                if (GpuInvoke.CountNonZero(gpuMask) &gt;= 4)\r\n                {\r\n                    int nonZeroCount = Features2DToolbox.VoteForSizeAndOrientation(modelKeyPoints, observedKeyPoints, indices, mask, 1.5, 20);\r\n                    if (nonZeroCount &gt;= 4)\r\n                        homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(modelKeyPoints, observedKeyPoints, indices, mask, 2);\r\n                }\r\n            }\r\n            else\r\n            {\r\n                modelKeyPoints = surfCPU.DetectKeyPointsRaw(modelImage, null);\r\n                Matrix&lt;float&gt; modelDescriptors = surfCPU.ComputeDescriptorsRaw(modelImage, null, modelKeyPoints);\r\n                observedKeyPoints = surfCPU.DetectKeyPointsRaw(observedImage, null);\r\n                Matrix&lt;float&gt; observedDescriptors = surfCPU.ComputeDescriptorsRaw(observedImage, null, observedKeyPoints);\r\n                BruteForceMatcher&lt;float&gt; matcher = new BruteForceMatcher&lt;float&gt;(DistanceType.L2);\r\n                matcher.Add(modelDescriptors);\r\n                indices = new Matrix&lt;int&gt;(observedDescriptors.Rows, k);\r\n                Matrix&lt;float&gt; dist = new Matrix&lt;float&gt;(observedDescriptors.Rows, k);\r\n                matcher.KnnMatch(observedDescriptors, indices, dist, k, null);\r\n                mask = new Matrix&lt;byte&gt;(dist.Rows, 1);\r\n                mask.SetValue(255);\r\n                Features2DToolbox.VoteForUniqueness(dist, uniquenessThreshold, mask);\r\n                int nonZeroCount = CvInvoke.cvCountNonZero(mask);\r\n                if (nonZeroCount &gt;= 4)\r\n                {\r\n                    nonZeroCount = Features2DToolbox.VoteForSizeAndOrientation(modelKeyPoints, observedKeyPoints, indices, mask, 1.5, 20);\r\n                    if (nonZeroCount &gt;= 4)\r\n                        homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(modelKeyPoints, observedKeyPoints, indices, mask, 2);\r\n                }\r\n            }\r\n            #region G\u00d6R\u00dcNT\u00dcN\u00dcN \u0130\u015eLENMES\u0130\r\n            Image&lt;Bgr, Byte&gt; result = Features2DToolbox.DrawMatches(modelImage, modelKeyPoints, observedImage, observedKeyPoints, indices, new Bgr(255, 255, 255), new Bgr(255, 255, 255), mask, Features2DToolbox.KeypointDrawType.DEFAULT);\r\n            #endregion\r\n            if (homography != null)\r\n            {\r\n                Rectangle rect = modelImage.ROI;\r\n                PointF&#x5B;] pts = new PointF&#x5B;] {\r\n               new PointF(rect.Left, rect.Bottom),\r\n               new PointF(rect.Right, rect.Bottom),\r\n               new PointF(rect.Right, rect.Top),\r\n               new PointF(rect.Left, rect.Top)};\r\n                homography.ProjectPoints(pts);\r\n\r\n                #region TESP\u0130T ED\u0130LEN NESNEN\u0130N \u00c7\u0130Z\u0130LMES\u0130\r\n                result.DrawPolyline(Array.ConvertAll&lt;PointF, Point&gt;(pts, Point.Round), true, new Bgr(Color.Red), 3);\r\n                #endregion\r\n            }\r\n            return result;\r\n        }\r\n    }\r\n<\/pre>\n<p>Evet&#8230; SURF algoritmas\u0131n\u0131 yukar\u0131daki gibi olu\u015fturmu\u015f olduk. Yap\u0131sal olarak teknik boyutta \u00e7ok fazla teferruat bar\u0131nd\u0131rd\u0131\u011f\u0131 i\u00e7in \u015fimdilik yukar\u0131daki kod blo\u011funun sat\u0131rlar\u0131na izahet getirmiyorum. Lakin bu s\u0131n\u0131f\u0131n sa\u011fl\u0131kl\u0131 bir \u015fekilde \u00e7al\u0131\u015ft\u0131\u011f\u0131ndan birazdan g\u00f6zlerimizle emin olaca\u011f\u0131z.<\/p>\n<p>\u015eimdi s\u0131ra, kameradan elde etti\u011fimiz g\u00f6r\u00fcnt\u00fcde SURF algoritmas\u0131yla taray\u0131p alg\u0131layaca\u011f\u0131m\u0131z nesneyi sisteme tan\u0131tmaya gelmi\u015ftir. Kullanaca\u011f\u0131m\u0131z nesne \u00e7ok sevip de\u011fer verdi\u011fim Say\u0131n Yazar \u00dcmit Do\u011fan Beyefendi&#8217;nin &#8220;Atat\u00fcrk&#8217;\u00fcn \u0130stihbarat Faaliyetleri &#8211; Milli Ajanlar\u0131m\u0131z&#8221; isimli kitab\u0131d\u0131r.(<em>Kesinlikle okuman\u0131z\u0131 ve okutturman\u0131z\u0131 tavsiye ederim \ud83d\ude09<\/em>) Velhas\u0131l bu kitab\u0131n bir g\u00f6rselini internetten indirip elde edebilir ya da direkt olarak nesneyi kamera \u00fczerinden de manuel olarak taray\u0131p g\u00f6rselini sa\u011flayabiliriz. Projede bu g\u00f6rseli tutmak i\u00e7in Resource dosyalar\u0131n\u0131 kulland\u0131\u011f\u0131m\u0131 ba\u015ftan belirteyim.<\/p>\n<p>Alg\u0131lataca\u011f\u0131m\u0131z nesnenin g\u00f6rselini temin ederek sisteme entegre ettikten sonra s\u0131ra yukar\u0131daki olu\u015fturmu\u015f oldu\u011fumuz static yap\u0131daki &#8220;SURFAlgoritmasi&#8221; isimli s\u0131n\u0131f\u0131 kullanmaya yani i\u00e7eri\u011fimizin as\u0131l i\u015flevini icra etmeye gelmi\u015ftir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n        private void Form1_Load(object sender, EventArgs e)\r\n        {\r\n            Capture capture = new Capture();\r\n            capture.Start();\r\n            capture.ImageGrabbed += (a, b) =&gt;\r\n            {\r\n                try\r\n                {\r\n                    var image = capture.RetrieveBgrFrame();\r\n\r\n                    var SURFimage = SURFAlgoritmasi.Draw(new Image&lt;Gray, Byte&gt;(Resimler.nesne), image.Convert&lt;Gray, byte&gt;());\r\n                    pictureBox1.Image = SURFimage.ToBitmap();\r\n                }\r\n                catch\r\n                {\r\n\r\n                }\r\n            };\r\n        }\r\n<\/pre>\n<p>Yukar\u0131daki kod blo\u011funda oldu\u011fu gibi SURF algoritmas\u0131n\u0131 kullanarak kameradan gelen g\u00f6r\u00fcnt\u00fc \u00fczerinde elimizdeki g\u00f6r\u00fcnt\u00fcleri k\u0131yaslamakta ve nesne tespitini ger\u00e7ekle\u015ftirmekteyiz. \u015euana kadar yapm\u0131\u015f oldu\u011fumuz i\u015flemin faaliyetini a\u015fa\u011f\u0131daki videodan da inceleyebilirsiniz.<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/L8VXwhL4MLY\" frameborder=\"0\" allowfullscreen><\/iframe><\/p>\n<p>E\u011fer ki, nesnenin g\u00f6r\u00fcnt\u00fc \u00e7\u0131kt\u0131s\u0131na dahil edilmeden sadece tespit edilmesini istiyorsan\u0131z &#8220;SURFAlgoritmasi&#8221; s\u0131n\u0131f\u0131ndaki &#8220;G\u00d6R\u00dcNT\u00dcN\u00dcN \u0130\u015eLENMES\u0130&#8221; isimli region\u0131n i\u00e7erisini a\u015fa\u011f\u0131daki \u00e7al\u0131\u015fma ile de\u011fi\u015ftirmeniz yeterlidir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            Image&lt;Bgr, Byte&gt; result = observedImage.Convert&lt;Bgr, byte&gt;();\r\n<\/pre>\n<p>Bu \u015fekilde projeyi derleyip \u00e7al\u0131\u015ft\u0131rd\u0131\u011f\u0131m\u0131z vakit SURF algoritmas\u0131n\u0131 a\u015fa\u011f\u0131daki videoda oldu\u011fu gibi kullanabilmekteyiz.<br \/>\n<iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/5eNTIfBXKAo\" frameborder=\"0\" allowfullscreen><\/iframe><\/p>\n<p>G\u00f6rd\u00fc\u011f\u00fcn\u00fcz \u00fczere SURF algoritmas\u0131 ile elimizdeki g\u00f6r\u00fcnt\u00fc \u00fczerinde belirledi\u011fimiz bir nesneyi tarayabilmekte ve alg\u0131layabilmekteyiz. Her ne kadar benim ihtiyar bilgisayar\u0131m bu algoritman\u0131n h\u0131z\u0131na hakk\u0131yla e\u015flik edemesede yine de algoritman\u0131n y\u00fcksek performansl\u0131 i\u015fleyi\u015fine ve i\u015flevselli\u011fine \u015fahitlik etmi\u015f bulunmaktas\u0131n\u0131z.<\/p>\n<p>Sonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, \u015euana kadar g\u00f6r\u00fcnt\u00fc i\u015fleme \u00fczerine yapm\u0131\u015f oldu\u011fumuz t\u00fcm \u00e7al\u0131\u015fmalar neticesinde bir \u00e7ok Image Processing algoritmas\u0131n\u0131n mevcut oldu\u011fundan bahsetmi\u015f bulunmaktay\u0131z. Bu algoritmalar aras\u0131nda; g\u00f6r\u00fcnt\u00fc \u00fczerinde bir nesneyi alg\u0131lamam\u0131z\u0131 sa\u011flayan ve bu i\u015flemi yaparken boyut,&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":6733,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1905,1904],"tags":[1908,1982,1980,1981,1979],"class_list":["post-6886","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-emgucv","category-goruntu-isleme","tag-emgucv","tag-emgucv-surf","tag-emgucv-surf-algoritmasi","tag-surf","tag-surf-algoritmasi"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/6886","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=6886"}],"version-history":[{"count":0,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/6886\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/6733"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=6886"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=6886"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=6886"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}