检测矩形经过黄色像素

2024-05-04

我有一个关于检测移动和可能旋转的矩形何时经过面板背景图像的黄色像素的最佳方法的疑问。

我有一个方法,它接受一个图像和一个点,如果该点是黄色像素的点,则返回 true。我需要这种颜色检测来实现我的游戏功能,如果汽车(玩家)驶过赛道的黄色边界,它将重置汽车(玩家)。该方法如下图所示:

private Boolean isYellow(Image image, Point point)
{
   Bitmap bitmap = new Bitmap(image);
   Color color = bitmap.GetPixel(point.X, point.Y);

   return (color.R > 220 && color.G > 220 && color.B < 200);
}

以前,为了检测玩家矩形是否越过黄色,我根据对象的 X 和 Y 值提供的矩形位置进行检查。问题在于该位置是水平矩形的左上角,这意味着汽车几乎可以完全驶离赛道而不会被检测到。

我想通过检查矩形覆盖的所有点来解决这个问题。这并不像看起来那么简单,因为矩形可能会旋转。我的绘图和运动逻辑如下所示:

public void draw(Graphics g)
{
   int dx = rectangle.X + (rectangle.Height / 2);
   int dy = rectangle.Y + (rectangle.Width / 2);

   g.ScaleTransform(xScale, yScale);
   g.TranslateTransform(dx, dy);
   g.RotateTransform((float) ((180 * angle) / Math.PI));
   g.TranslateTransform(-dx, -dy);
   g.DrawImage(image, rectangle.X, rectangle.Y);
   g.ResetTransform();
}

public void move(uRaceGame game, Panel panel)
{
   double cos = Math.Cos(angle), sin = Math.Sin(angle);
   int xLocation = 200;
   int yLocation = 200;

   xLocation = (int) Math.Floor(rectangle.X + (cos * game.moveDir * 60)); 
   yLocation = (int) Math.Floor(rectangle.Y + (sin * game.moveDir * 60)); 

   angle = (angle + (game.rotateDir * (Math.PI / 128))) % (Math.PI * 2);

   if (xLocation * xScale > panel.Width - (rectangle.Width * cos) || yLocation * yScale > panel.Height - (rectangle.Width * sin) - 5 || xLocation * xScale < 0 || yLocation * yScale < 5) return;

   rectangle.Location = new Point(xLocation, yLocation);
}

我尝试但未能创建一种方法来转换角的坐标并找出矩形的中间,但这不起作用,并且黄色检测会在非常模糊的地方触发:

public Point getCentre()
{
    int cX = (int) (rectangle.X + ((rectangle.Width / 2) / xScale)), cY = (int) (rectangle.Y + ((rectangle.Height / 2) / yScale));
    float tempX = (rectangle.X - cX), tempY = (rectangle.Y - cY);

    double rX = (tempX * Math.Cos(angle)) - (tempY * Math.Sin(angle));
    double rY = (tempX * Math.Sin(angle)) - (tempY * Math.Cos(angle));

    return new Point((int) ((rX + cX) * xScale), (int) ((rY + cY) * yScale));
}

我真的很感激任何关于如何解决这个问题的建议。我包含了翻译和黄色检测代码,以防我在尝试中偏离了几英里而其他人有更好的想法。

非常感谢。


我想到了两种方法:

  • 您可以创建沿着汽车矩形倾斜边的循环
  • 或者您可以将汽车复制到倾斜位图并正常循环。

这是第二种方法的示例。

它使用一个LockBits检测方法Yellow你的代码在Bitmap.

它通过从原始文件复制位图来准备该位图BackgroundImage未旋转。

这是结果,包括一个控件Panel显示倾斜的矩形:



这是黄色取景器功能。它使用 Lockbits 来提高速度:

using System.Runtime.InteropServices;
using System.Drawing.Imaging;

public bool testForYellowBitmap(Bitmap bmp)
{
    Size s1 = bmp.Size;
    PixelFormat fmt = new PixelFormat();
    fmt = bmp.PixelFormat;
    Rectangle rect = new Rectangle(0, 0, s1.Width, s1.Height);
    BitmapData bmp1Data = bmp.LockBits(rect, ImageLockMode.ReadOnly, fmt);
    byte bpp1 = 4;
    if (fmt == PixelFormat.Format24bppRgb) bpp1 = 3;
    else if (fmt == PixelFormat.Format32bppArgb) bpp1 = 4; else return false; // throw!!
    int size1 = bmp1Data.Stride * bmp1Data.Height;
    byte[] data1 = new byte[size1];
    System.Runtime.InteropServices.Marshal.Copy(bmp1Data.Scan0, data1, 0, size1);
    for (int y = 0; y < s1.Height; y++)
    {
        for (int x = 0; x < s1.Width; x++)
        {
            Color c1;
            int index1 = y * bmp1Data.Stride + x * bpp1;
            if (bpp1 == 4)
                c1 = Color.FromArgb(data1[index1 + 3], data1[index1 + 2],
                                    data1[index1 + 1], data1[index1 + 0]);
            else c1 = Color.FromArgb(255, data1[index1 + 2], 
                                          data1[index1 + 1], data1[index1 + 0]);
            if (c1.R > 220 && c1.G > 220 && c1.B < 200) 
               { bmp.UnlockBits(bmp1Data); return true; }
        }
    }
    bmp.UnlockBits(bmp1Data);
    return false;
}

我准备了Bitmap来比较在MouseMove。变量w, h, w2, h2保持汽车尺寸的宽度、高度和一半。源位图位于drawPanel1.BackgroundImage。当前角度位于TrackBar tr_a.Value。为了进一步控制,我还以白色显示旋转的汽车矩形。

private void drawPanel1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button.HasFlag(MouseButtons.Left))
    {
        Size sz = drawPanel1.BackgroundImage.Size;
        Rectangle rectSrc = new Rectangle(e.X - w2, e.Y - h2, w, h);
        Rectangle rectTgt = new Rectangle(e.X - w, e.Y - h, 2 * w, 2 * h);

        using (Graphics g = drawPanel1.CreateGraphics())  // start optional
        {
            g.TranslateTransform(e.X, e.Y);
            g.RotateTransform(trb_a.Value);
            g.TranslateTransform(-e.X, -e.Y);
            drawPanel1.Refresh();
            g.DrawRectangle(Pens.White, rectSrc);
        }

        using (Graphics g = drawPanel2.CreateGraphics())
        {                                                      // end optional
            using (Bitmap bmp = new Bitmap(sz.Width, sz.Height))
            using (Graphics g2 = Graphics.FromImage(bmp))
            {
                g2.TranslateTransform(e.X, e.Y);
                g2.RotateTransform(-trb_a.Value);
                g2.TranslateTransform(-e.X, -e.Y);
                g2.DrawImage(drawPanel1.BackgroundImage, rectTgt, rectTgt, 
                             GraphicsUnit.Pixel);
                drawPanel2.Refresh();
                g.DrawImage(bmp, rectSrc, rectSrc, GraphicsUnit.Pixel);
                Text = testForYellowBitmap(bmp) ? "!!YELLOW!!" : "";
            }
        }
    }

第一种方法会使用类似的LockBits方法,但内部有沿着汽车矩形旋转边的循环,使用floats使用循环变量来计算 x 坐标。这些数据应在汽车尺寸或角度的每次变化时准备。代码有点长,但也应该更快一点。

第二种方法的优点是使用ClippingRegion on the Graphics对象可以检查任意形状,而第一种方法可以轻松修改为凹多边形,但不能修改为弯曲形状。

这是检查代码的改编版本first版本:

public bool testForYellowBitmapTilt(Bitmap bmp, List<int> leftPts, 
                                    List<int> rightPts, Point topLeft)
{
    Size s1 = bmp.Size;
    PixelFormat fmt = new PixelFormat();
    fmt = bmp.PixelFormat;
    Rectangle rect = new Rectangle(0, 0, s1.Width, s1.Height);
    BitmapData bmp1Data = bmp.LockBits(rect, ImageLockMode.ReadOnly, fmt);
    byte bpp1 = 4;
    if (fmt == PixelFormat.Format24bppRgb) bpp1 = 3;
    else if (fmt == PixelFormat.Format32bppArgb) bpp1 = 4; 
         else return false; // or throw!!
    if (leftPts.Count != rightPts.Count) return false; // or throw!!

    int size1 = bmp1Data.Stride * bmp1Data.Height;
    byte[] data1 = new byte[size1];
    System.Runtime.InteropServices.Marshal.Copy(bmp1Data.Scan0, data1, 0, size1);

    for (int y = 0; y < (leftPts.Count); y++)
    {
        for (int x = leftPts[y] + topLeft.X; x < rightPts[y] + topLeft.X; x++)
        {
            Color c1;

            int index1 = (y + topLeft.Y) * bmp1Data.Stride + x * bpp1;
            if (index1 > 0)
            {
                if (bpp1 == 4)
                    c1 = Color.FromArgb(data1[index1 + 3], data1[index1 + 2], 
                                        data1[index1 + 1], data1[index1 + 0]);
                else c1 = Color.FromArgb(255, data1[index1 + 2],
                                        data1[index1 + 1], data1[index1 + 0]);

                if (c1.R > 220 && c1.G > 220 && c1.B < 200) 
                   { bmp.UnlockBits(bmp1Data); return true; }
            }
        }
    }
    bmp.UnlockBits(bmp1Data);
    return false;
}

左侧和右侧坐标存储在这里:

List<int> leftPts = new List<int>();
List<int> rightPts = new List<int>();
Point top = Point.Empty;


void getOuterPoints(List<PointF> corners, out List<int> leftPts, 
                    out List<int> rightPts, out Point top)
{
    leftPts = new List<int>();
    rightPts = new List<int>();

    PointF left = corners.Select(x => x).OrderBy(x => x.X).First();
    PointF right = corners.Select(x => x).OrderByDescending(x => x.X).First();
            top = Point.Round(corners.Select(x => x).OrderBy(x => x.Y).First());
    PointF bottom = corners.Select(x => x).OrderByDescending(x => x.Y).First();

    int w1 = -(int)(top.X - left.X);
    int w2 = -(int)(left.X - bottom.X );
    int h1 = (int)(left.Y - top.Y);
    int h2 = (int)(bottom.Y - left.Y);

    float d1 = 1f * w1 / h1;
    float d2 = 1f * w2 / h2;

    for (int y = 0; y < h1; y++) leftPts.Add( (int)(y * d1) );
    for (int y = 0; y < h2; y++) leftPts.Add( (int)(y * d2 + w1));

    for (int y = 0; y < h2; y++) rightPts.Add( (int)(y * d2));
    for (int y = 0; y < h1; y++) rightPts.Add(  (int)(y * d1 + w2));
}

你需要在四个角上喂食List<PointF>以任何顺序;这top可以是任何东西,它将在方法中设置。坐标是相对于汽车的,因此当汽车移动时它们不会改变。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

检测矩形经过黄色像素 的相关文章

  • 适合初学者的良好调试器教程[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有谁知道一个好的初学者教程 在 C 中使用调试器 我感觉自己好像错过了很多 我知道怎么做 单步执行代码并查看局部变量 虽然这常常给我带来问
  • 如何捕获未发送到 stdout 的命令行文本?

    我在项目中使用 LAME 命令行 mp3 编码器 我希望能够看到某人正在使用什么版本 如果我只执行 LAME exe 而不带参数 我会得到 例如 C LAME gt LAME exe LAME 32 bits version 3 98 2
  • 在c#中执行Redis控制台命令

    我需要从 Redis 控制台获取 客户端列表 输出以在我的 C 应用程序中使用 有没有办法使用 ConnectionMultiplexer 执行该命令 或者是否有内置方法可以查找该信息 CLIENT LIST是 服务器 命令 而不是 数据库
  • 查找进程的完整路径

    我已经编写了 C 控制台应用程序 当我启动应用程序时 不使用cmd 我可以看到它列在任务管理器的进程列表中 现在我需要编写另一个应用程序 在其中我需要查找以前的应用程序是否正在运行 我知道应用程序名称和路径 所以我已将管理对象搜索器查询写入
  • 为什么在 WebApi 上下文中在 using 块中使用 HttpClient 是错误的?

    那么 问题是为什么在 using 块中使用 HttpClient 是错误的 但在 WebApi 上下文中呢 我一直在读这篇文章不要阻止异步代码 https blog stephencleary com 2012 07 dont block
  • 当一组凭据下的计划任务启动的进程在另一组凭据下运行另一个程序时,Windows 是否有限制

    所以我有一个简单的例子 其中我有应用程序 A 它对用户 X 本地管理员 有一些硬编码的凭据 然后它使用硬编码的绝对路径启动带有这些凭据的应用程序 B A 和 B 以及 dotnet 控制台应用程序 但是它们不与控制台交互 只是将信息写入文件
  • Python 属性和 Swig

    我正在尝试使用 swig 为一些 C 代码创建 python 绑定 我似乎遇到了一个问题 试图从我拥有的一些访问器函数创建 python 属性 方法如下 class Player public void entity Entity enti
  • C# 存档中的文件列表

    我正在创建一个 FileFinder 类 您可以在其中进行如下搜索 var fileFinder new FileFinder new string C MyFolder1 C MyFolder2 new string
  • 类型约束

    我有以下类层次结构 class Header IEnumerable
  • 打破 ReadFile() 阻塞 - 命名管道 (Windows API)

    为了简化 这是一种命名管道服务器正在等待命名管道客户端写入管道的情况 使用 WriteFile 阻塞的 Windows API 是 ReadFile 服务器已创建启用阻塞的同步管道 无重叠 I O 客户端已连接 现在服务器正在等待一些数据
  • 使用valgrind进行GDB远程调试

    如果我使用远程调试gdb我连接到gdbserver using target remote host 2345 如果我使用 valgrind 和 gdb 调试内存错误 以中断无效内存访问 我会使用 target remote vgdb 启动
  • 如何在 Qt 应用程序中通过终端命令运行分离的应用程序?

    我想使用命令 cd opencv opencv 3 0 0 alpha samples cpp cpp example facedetect lena jpg 在 Qt 应用程序中按钮的 clicked 方法上运行 OpenCV 示例代码
  • IQueryable 单元或集成测试

    我有一个 Web api 并且公开了一个端点 如下所示 api 假期 name name 这是 Web api 的控制器 get 方法 public IQueryable
  • 在 NaN 情况下 to_string() 可以返回什么

    我使用 VS 2012 遇到了非常令人恼火的行为 有时我的浮点数是 NaN auto dbgHelp std to string myFloat dbgHelp最终包含5008角色 你不能发明这个东西 其中大部分为0 最终结果是 0 INF
  • 在mysql连接字符串中添加应用程序名称/程序名称[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我正在寻找一种解决方案 在连接字符串中添加应用程序名称或程序名称 以便它在 MySQL Workbench 中的 客户端连接 下可见 SQL
  • WebBrowser.Print() 等待完成。 。网

    我在 VB NET 中使用 WebBrowser 控件并调用 Print 方法 我正在使用 PDF 打印机进行打印 当调用 Print 时 它不会立即启动 它会等到完成整个子或块的运行代码 我需要确保我正在打印的文件也完整并继续处理该文件
  • 这个可变参数模板示例有什么问题?

    基类是 include
  • 如何减少具有多个单元的 PdfPTable 的内存消耗

    我正在使用 ITextSharp 创建一个 PDF 它由单个 PdfTable 组成 不幸的是 对于特定的数据集 由于创建了大量 PdfPCell 我遇到了内存不足异常 我已经分析了内存使用情况 我有近百万个单元格的 1 2 在这种情况下有
  • 是否可以在不连接数据库的情况下检索 MetadataWorkspace?

    我正在编写一个需要遍历实体框架的测试库MetadataWorkspace对于给定的DbContext类型 但是 由于这是一个测试库 我宁愿不连接到数据库 它引入了测试环境中可能无法使用的依赖项 当我尝试获取参考时MetadataWorksp
  • OpenCV SIFT 描述符关键点半径

    我正在深入研究OpenCV的SIFT描述符提取的实现 https github com Itseez opencv blob master modules nonfree src sift cpp 我发现了一些令人费解的代码来获取兴趣点邻域

随机推荐

  • 同步迭代 javascript 对象

    我有一个像这样的对象 let myObject db1 db1 file1Id db1 file2Id db 1file3Id db2 db2 file1Id db2 file2Id 我遍历这个对象并在每次迭代中 我连接到数据库 检索文件
  • jcop是在java卡中安装小程序的唯一方法吗?

    我正在尝试理解java卡的概念 我有一些疑问 我想与大家分享 也许你会对我有任何最好的建议 Jcop 我在某处读到 Java Card OpenPlatform JCOP 是由 IBM Z rich Research Laboratory
  • java运算符“->”的含义[重复]

    这个问题在这里已经有答案了 下面的代码取自 SpringBoot 应用程序的初始化 java 运算符 gt 的含义是什么 Bean public EmbeddedServletContainerCustomizer containerCus
  • 在 hibernate JPA 的 getReference() 之后,如果不使用 setter 发出 select 则无法更新

    我有以下方法 Transactional public void savethis EntityObject t entityManagerTreasury getReference EntityObject class 1 t setAc
  • webapp 在 iOS 7 中无法正确缩放

    有人遇到同样的问题吗 content width device width 当我的 iphone 仍然是 i0S 6 并且我刚刚更新到 iOS 7 并且似乎不再工作时它就可以工作 或者可能是其他原因导致了问题 有人有什么想法吗 现在我正在使
  • GSON 没有为接口类型调用我的 TypeAdapter

    GSON 似乎在使用某种技巧 它查看 JavaBean 的内部字段 而不是使用可公开访问的属性信息 不幸的是 这对我们来说不会成功 因为我们神奇地创造的豆子充满了我不希望它存储的私人领域 Test public void testJson
  • numpy.ndarray 对象不被垃圾回收

    在尝试微调某些 C C 函数的 Python 绑定中的一些内存泄漏时 我发现了一些与 Numpy 数组的垃圾收集相关的奇怪行为 为了更好地解释这种行为 我创建了几个简化的案例 该代码是使用memory profiler 其输出紧随其后 当涉
  • 将声音添加到标记数组 - 谷歌地图 javascript

    我是新来的 所以我知道我没有任何可信度 我是一名艺术家 对编程很陌生 所以我理解是否没有人会承担这个任务 我发布这篇文章是因为这是一个简单的问题 S 这是创建多个标记的代码 主要来自谷歌开发者网站 它工作正常并为每个标记创建一个自定义图标
  • 是否可以强制 html canvas 标签显示子项?

    基本上和我问的一模一样 我希望以下工作能够发挥作用
  • 为什么我的 Java 代码执行 bash 命令不正确?

    我试图让我的 Java 程序与 Linux bash 交互 但出了问题 我有一个简单的可执行文件prog从中读取一个整数stdin并输出其平方 执行中 echo 5 prog 从 bash 本身打印正确答案25 in stdout但运行 i
  • 如何删除 BeautifulSoup 中的空格

    我正在使用 BeautifulSoup 解析一堆 HTML 除了一个小问题外 一切进展顺利 我想将输出保存到单行字符串中 以下内容作为我当前的输出 li span class plaincharacterwrap break Zazzafo
  • 为什么 split(' ') 试图变得(太)聪明了?

    我刚刚发现以下奇怪的行为String split a tb c nd split gt a b c d a tb c nd split gt a b c d a tb c nd split gt a tb c nd 来源 https git
  • 在 SVN 存储库中导入 Android Studio 项目的正确方法是什么?

    我正在尝试在 SVN 存储库中导入 Android Studio 项目 我显然尝试过 VCS gt 导入到版本控制 gt 导入到 Subversion 但问题是 即使取消选中Include ignored resources框内 软件不断将
  • 当属性名称与实体名称匹配时,实体框架将“1”附加到属性名称

    我正在使用实体框架 4 0 版使用数据库优先方法创建模型 在数据库中 有许多表包含与其父表名称相同的列 例如我们有 表 State 包含 State 和 StateName 列 表状态 包含状态和描述列 问题在于 当将这些表之一导入 EF
  • gcc 的 -Wbad-function-cast 的目的是什么?

    根据此处答案的建议 我打开了 Wbad function cast看看我的代码是否有 gcc 可以捕获的任何不良行为 结果出现了这个示例 unsigned long n int crossover int pow n 14 这里并不重要cr
  • 如何制作 U 矩阵?

    为了可视化一个 U 矩阵到底是如何构建的自组织映射 http en wikipedia org wiki Self organizing map 更具体地说 假设我有一个 3x3 节点的输出网格 已经经过训练 我如何从中构造一个 U 矩阵
  • 使用 Spring mvc 和 MockMVC 上传文件

    我已成功将图像文件上传到WebContent resources uploads image jsp 但我在使用 MockMvc 进行测试时遇到了问题 当我运行测试用例时 我遇到了异常文件未找到 and 拒绝访问 控制器看起来像这样 Req
  • Flurry 与 Android 应用程序集成出现错误“无法找到类 'com.flurry.sdk.i',从方法 com.flurry.sdk.hu.a 引用”

    这是我到目前为止所尝试过的 public class ScoreUpApp extends Application private static ScoreUpApp scoreUpDataCache public static final
  • 局部敏感哈希 - Elasticsearch

    有没有允许在 Elasticsearch 上使用 LSH 的插件 如果是的话 您能否指出该位置并告诉我如何使用它 谢谢 编辑 我发现ES使用了MinHash插件 我怎样才能用这个来比较文件呢 查找重复项的最佳设置是什么 有一个Elastic
  • 检测矩形经过黄色像素

    我有一个关于检测移动和可能旋转的矩形何时经过面板背景图像的黄色像素的最佳方法的疑问 我有一个方法 它接受一个图像和一个点 如果该点是黄色像素的点 则返回 true 我需要这种颜色检测来实现我的游戏功能 如果汽车 玩家 驶过赛道的黄色边界 它