单位小于一个像素,屏幕截图在屏幕的较大部分内搜索屏幕的部分图像

时间:2012-08-29 14:04:42

标签: c# bitmap image-comparison

整个问题是,使用CopyFromScreen()方法我能够将图像(先前捕获的)与捕获的图像进行比较,因为它实际上是从该特定屏幕捕获的。

或更简单地说,例如,一个图标,从桌面裁剪并保存为图像以及引用其位置(点)及其大小(大小(h,w))的文本文件

所以当我们通过File.WriteAllBytes(byte []使它.bar)将capture.bar引用到文件+ cuptured.txt并参考位置和大小时,我们将副本保存到hdd及其位置和大小文本。 (我没有发布所有代码,但它工作正常,如果有人需要它..我分享感觉自由)

我实现这一点的方法是使用我制作DoCopyFScr()的方法来破坏使用Bitmap2ByteArr()的屏幕部分 - 将位图保存为ByteArr 然后在需要时使用byte [] - 保存,与其在屏幕上捕获的位置进行比较。

    public void DoCopyFScr(Point SourceP, Size Mysz, string initDir, string Fname, bool SaveIt, bool DoCompare)
    {

        SetForegroundWindow(A window handle suplied here);
        pause(200);
        Point pZero = new Point(0, 0);

        using (Bitmap bitmap = new Bitmap(Mysz.Width, Mysz.Height))
        {
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                g.CopyFromScreen(SourceP, pZero, Msyz);
            }
            Image img = (Image)bitmap;
            Clipboard.SetImage(img);
            ItsCopiedFromScreen = true;
            MyBtmpToByteArr b2arr = new MyBtmpToByteArr();// inststance of My bitmap to byte[]

            AAdToAppLog("start Converting Bitmap To ByteArr");// logging programs activity in a listview via reflection
            MyCuptredBtmpToolBox.CuptByteArr = b2arr.Bitmap2ByteArr(bitmap);
            AAdToAppLog("Done Convertion ArrSize " + b2arr.Bitmap2ByteArr(bitmap).Length + ", Resting CopyDestionation SelctdIndx");
                                Combo_CopyFromScrn.SelectedIndex = 0;
            if (SaveIt)
            {
                string btmpsRefrenceSave = MyCuptredBtmpToolBox.SourceX_Cuptured.ToString() + "," + MyCuptredBtmpToolBox.SourceY_Cuptured.ToString() + "," + MyCuptredBtmpToolBox.RectWidth_Cuptured.ToString() + "," + MyCuptredBtmpToolBox.RectHeight_Cuptured.ToString() + "," + TBX_FileSaveName.Text;
                if (ItsLoadedFromFile)
                {
                    File.WriteAllBytes(initDir + TBX_FileSaveName.Text, b2arr.Bitmap2ByteArr(bitmap));// See next block Method Bitmap2ByteArr method
                    File.WriteAllText(initDir + TBX_FileSaveName.Text.Replace("bar", "txt"), btmpsRefrenceSave);
                }
                else
                {
                    File.WriteAllBytes(initDir + TBX_FileSaveName.Text + ExtBar, b2arr.Bitmap2ByteArr(bitmap));
                    File.WriteAllText(initDir + TBX_FileSaveName.Text.Replace("bar", "txt") + ExtTXT, btmpsRefrenceSave);
                }
                //MyCuptredBtmpToolBox.CupturedStaticBmp.Save(MyCuptredBtmpToolBox.FnameToSave.Replace(".bar", ".") + ExtJpg, ImageFormat.Jpeg);
                bitmap.Save(initDir + TBX_FileSaveName.Text + ExtJpg, ImageFormat.Jpeg);
            }
            if (DoCompare)
            {
                AAdToAppLog("starting Compare " + Fname +" With Btmp2Arr From Screen");
                R_ComparwByteArrClass tstCmp = new R_ComparwByteArrClass();
                if (itsAutomated)
                {
                    CompareByt2Btmp = R_ComparwByteArrClass.ByteArrCompare(DoAutoLoadCuptByteArr(initDir, Fname + ExtBar), b2arr.Bitmap2ByteArr(bitmap));
                }
                else
                {
                    CompareByt2Btmp = R_ComparwByteArrClass.ByteArrCompare(MyLoadedBtmpToolBox.LoadedByteArr, b2arr.Bitmap2ByteArr(bitmap));
                }
                bring(MyApp);
                AAdToAppLog(CompareByt2Btmp.ToString());

            }
        }

    }

位图到ByteArr类,其方法是将被破坏的btmp转换为byte []

  public class MyBtmpToByteArr
    {


        public byte[] Bitmap2ByteArr(Bitmap btmpToConvertintoByteArr)
        {


            //Convert image to a byte array
            System.Drawing.ImageConverter MyImgCvrtr = new System.Drawing.ImageConverter();
            byte[] btImage = new byte[1];
            btImage = (byte[])MyImgCvrtr.ConvertTo(btmpToConvertintoByteArr, btImage.GetType());


            return btImage;
        }
    }

但是如果位置发生变化我无法识别,即使我在屏幕上给出了图像的新位置,但是当我进行测试时,使用油漆和转动网格我定位了相同裁剪的两个副本图像,我做了成功,但在一个真实的情况下,游戏屏幕有一个共享背景的几个图标,我尝试相互比较,不成功 即使我给了位置,是否有一个小于一个像素的单位也许游戏的图形使用一种像素的一小部分?或者也许是其他单位 mybe给定的位置Point1是X100 Y100的第一个图标,而另一个而不是200,200实际上是200.33,200.55左右...这就是为什么我没有得到死锁的位置/位置? ps我认为它使用的是一个直观的,如果不是它在openGL上最重要的肯定在directx上是否重要的​​是用于定位图像的单位是否存在小于像素的单位...并且常用? 如果不是,你将如何实现从x100到x150和y100到y150循环的功能,以便我可以搜索图像

2 个答案:

答案 0 :(得分:0)

您可能会看到的是渲染工件与缩放,锯齿或子像素提示的区别。

例如,基于WPF的应用程序与DPI无关,因此它们使用“显示点”而不是像素,并且您可以使用一小部分显示点来说明您所看到的行为类型。

“像素”是一个非常物理的东西(显示器上的点),但并非所有东西都严格地将1:1映射到真实世界的像素。

因此,你需要一个更聪明的机制来比较相似的图像 - this related stackoverflow post可能是一个很好的起点。

答案 1 :(得分:0)

制作了MySelf问题的第二部分

StpX,StpY限制循环最大迭代次数

原始Point是捕获的位置initPoint CountDown正在进行数学计算,直到结束还有多少轮,而在内部循环中,搜索成功时会触发“手动中断”

        Point SearchFromPoint = Point.Empty;
        Point initPoint = new Point(150, 100);
        Size imgSz = new Size(320, 240);
        int StpX = initPoint.X + 1, StpY = initPoint.Y + 1;

        int CountDownX, CountDownY;
        for (int StrtX = initPoint.X - extraX; StrtX < StpX; StrtX++)
        {
            SearchFromPoint.X = StrtX;
            for (int StrtY = initPoint.Y - extraY; StrtY < StpY; StrtY++)
            {
                CountDownX = (initPoint.X - StrtX); CountDownY=(initPoint.Y - StrtY);
                 SearchFromPoint.Y = StrtY;
                AAdToAppLog("Search Report For: " + imgName + " Still trying Search On " + CountDownX + ":" + CountDownY +" Point(" + SearchFromPoint.X + ", " + SearchFromPoint.Y + ")");
                DoCopyFScr(SearchFromPoint, tmpSz, initDir, Fname, false, true);
                    if (CompareByt2Btmp.ToString() == R_ComparwByteArrClass.CompHashResult.HashCompare_Ok.ToString())
                    {
                        same = true;
                        AAdToAppLog("Search Report For: " + imgName + "Search Completed Successfully On Try " + CountDownX + ":" + CountDownY);

                        break;
                    }
            }

        }

这就是我的想法......总结搜索方法而不是固定的已知位置场景。

如果有任何事情你想发表评论,可以免费发帖。