草庐IT

java - 是否有适当的算法来检测图形的背景颜色?

coder 2024-03-20 原文

在大学里,我们接到了一项作业,在给定图像的情况下,我们必须识别“图形”、它们的颜色以及其中的“像素组”数量。让我解释:



上图有一个 (在图像中可以有多个数字,但让我们暂时忘记这一点)。

  • Canvas 的背景颜色是 0,0 处的像素(在本例中为黄色)
  • 图形的边框颜色为黑色(可以是 Canvas 背景色以外的任何颜色)。
  • 图形的背景颜色为白色(也可以与 Canvas 的背景颜色相同)。
  • 一个图形只能有一种背景颜色。
  • 图中有两个像素组。一个是蓝色像素池,另一个是内部带有一些绿色的红色像素池。如您所见,像素组像素的颜色无关紧要(它只是与图形的背景颜色不同)。重要的是他们接触(甚至是对角线)这一事实。因此,尽管有两种不同的颜色,但无论如何,这样的组都被视为一种。
  • 如您所见,边框可以随心所欲地不规则。然而,它只有一种颜色。
  • 众所周知,像素组不会接触边界。
  • 有人告诉我,像素组的颜色可以是除图形背景颜色之外的任何颜色。我假设它可以与图形的边框颜色(黑色)相同。

  • 我们得到了一个能够拍摄图像并将它们转换为矩阵的类(每个元素都是一个代表像素颜色的整数)。

    就是这样。我正在用 Java 做这件事。

    到目前为止我做了什么
  • 遍历矩阵中的每个像素
  • 如果我发现一个与背景颜色不同的像素,我会认为它属于图形的边框。我将把这个像素称为 initialPixel从现在开始。
  • 请注意 initialPixel在我提供的图像中,是图左上角的黑色像素。我故意在那里做了一个锐利的剪裁来说明它。
  • 我现在的任务是找到图形的背景颜色(在本例中为白色)。

  • 但是我很难找到这样的背景颜色(白色)。这是我所做的最接近的方法,它适用于某些情况 - 但不适用于此图像:
  • 因为我知道边框的颜色,所以我可以找到第一个与 不同的颜色。南initialPixel .听起来是个好主意 - 它有时确实有效,但它不适用于提供的图像:在这种情况下它将返回黄色,因为 initialPixel与图的内容相差甚远。

  • 假设我确实找到了图形的背景颜色(白色),我的下一个任务是意识到图形中存在两个像素组。这个似乎更容易:
  • 由于我现在知道图形的背景颜色(白色),我可以尝试遍历图形中的每个像素,如果我找到一个不属于边框且不属于图形背景的像素,我已经可以知道有一个像素组。我可以开始一个递归函数来查找与此类组相关的所有像素并“标记”它们,以便在 future 的迭代中我可以完全忽略此类像素。

  • 我需要什么

    是的,我的问题是关于如何根据我之前描述的内容找到图形的背景颜色(请记住,它可以与整个图像的背景颜色相同 - 现在它是黄色,但也可以是白色)。

    我不需要任何代码——我只是在想一个合适的算法时遇到了麻烦。边界可以有如此奇怪的不规则线条这一事实让我很伤心。

    或者甚至更好:我一直做错了吗?也许我不应该太关注那个 initialPixel根本。也许一种不同的初始方法会起作用?是否有任何关于此类主题的文档/示例?我意识到有很多关于“计算机视觉”等的研究,但我找不到关于这个特定问题的太多信息。

    一些代码

    我用所有数字检索 vector 的函数:
    *注:Figure只是一个包含一些值的类,比如背景颜色和元素数量。
    public Figure[] getFiguresFromImage(Image image) {
        Figure[] tempFigures = new Figure[100];
        int numberOfFigures = 0;
        matrixOfImage = image.getMatrix();
        int imageBackgroundColor = matrixOfImage[0][0];
        int pixel = 0;
    
        for (int y = 0; y < matrixOfImage.length; ++y) {
            for (int x = 0; x < matrixOfImage[0].length; ++x) {
                pixel = matrixOfImage[y][x];
                if (!exploredPixels[y][x]) {
                    // This pixel has not been evaluated yet
                    if (pixel != imageBackgroundColor ) {
                        // This pixel is different than the background color
                        // Since it is a new pixel, I assume it is the initial pixel of a new figure
                        // Get the figure based on the initial pixel found
                        tempFigures[numberOfFigures] = retrieveFigure(y,x);
                        ++numberOfFigures;
                    }
                }
            }   
        }
    
        // ** Do some work here after getting my figures **
    
        return null;
    }
    

    那么,显然,函数 retrieveFigure(y,x)是我无法做到的。

    备注:
  • 出于学习目的,我不应该使用任何外部库。
  • 最佳答案

    解决此问题的一个好方法是将图像视为 graph ,其中每个颜色填充区域都有一个节点(本答案中的“组件”)。
    这是实现这种方法的一种方法:

  • 将所有像素标记为未访问。
  • 对于每个像素,如果该像素未被访问,则执行 flood fill其上的算法。在洪水填充期间,将每个连接的像素标记为已访问。
    现在您应该在您的图像(或“组件”)中有一个纯色区域的列表,所以您只需要弄清楚它们是如何相互连接的:
  • 找到像素与背景颜色组件相邻的组件 - 这是您的图形边框。请注意,您可以通过查找具有 0,0 像素的组件来找到背景颜色组件。
  • 现在找到像素与新发现的“图形边框”组件相邻的组件。将有两个这样的组件 - 选择一个不是背景的组件(即没有 0,0 像素)。这是你的人物背景。
  • 要找到像素组,只需计算与图形背景组件相邻的像素的组件数量(当然忽略图形边框组件)

  • 这种方法的优点:
  • 在 O(# 像素) 时间内运行。
  • 易于理解和实现。
  • 不假设背景颜色和图形背景颜色不同。

  • 为确保您了解迭代组件及其邻居的工作原理,以下是步骤 5 的示例伪代码实现:
    List<Component> allComponents; // created in step 2
    Component background; // found in step 3 (this is the component with the 0,0 pixel)
    Component figureBorder; // found in step 4
    List<Component> pixelGroups = new List<Component>(); // list of pixel groups
    
    for each Component c in allComponents:
        if c == background:
            continue;
        for each Pixel pixel in c.pixelList:
            for each Pixel neighbor in pixel.neighbors:
                if neighbor.getComponent() == figureBorder:
                    c.isPixelGroup = true;
    
    int numPixelGroups = 0;
    for each Component c in allComponents:
        if (c.isPixelGroup)
            numPixelGroups++;
    

    关于java - 是否有适当的算法来检测图形的背景颜色?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12995378/

    有关java - 是否有适当的算法来检测图形的背景颜色?的更多相关文章

    1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

      给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

    2. ruby - 检查数组是否在增加 - 2

      这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

    3. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

      我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

    4. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

      所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

    5. java - 等价于 Java 中的 Ruby Hash - 2

      我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

    6. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

      我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

    7. ruby-on-rails - 使用 Rmagick 或 ImageMagick 在背景上放置标题 - 2

      我有一张背景图片,我想在其中添加一个文本框。我想弄清楚如何将标题放置在其顶部的正确位置。(我使用标题是因为我需要自动换行功能)。现在,我只能让文本显示在左上角,但我需要能够手动定位它的开始位置。require'RMagick'require'Pry'includeMagicktext="Loremipsumdolorsitamet"img=ImageList.new('template001.jpg')img 最佳答案 这是使用convert的ImageMagick命令行的答案。如果你想在Rmagick中使用这个方法,你必须自己移植

    8. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

      我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

    9. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

      我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

    10. ruby - 检查日期是否在过去 7 天内 - 2

      我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/

    随机推荐