2009-12-20 206 views
4

我正在一个房地产网站上工作,我想写一个程序, 可以找出(分类)如果图像是平面图或公司标志。图像分类 - 检测平面图

因为我在php中写作,我会更喜欢php解决方案,但任何c + +或opencv解决方案也会很好。

平面图样品:

alt text http://www.rentingtime.com/uploads/listing/l0050/0000050930/68614.jpg

alt text http://www.rentingtime.com/uploads/listing/l0031/0000031701/44199.jpg

标志样本:

alt text http://www.rentingtime.com/uploads/listing/l0091/0000091285/95205.jpg

+0

你可能会更适合在自由程序员的网站上寻找;这有点超出了单个问题的范围。 – Amber 2009-12-20 08:32:34

+2

除非这些平面图文档易于表征,否则您不需要自由程序员,因为您需要一个充满博士学位的研发部门。没有人会在PHP中写出这样的想法。 – 2009-12-20 08:35:53

+3

http://www.townsvillefloorplans.com.au/images/logo.jpg既是...... – 2009-12-20 11:59:44

回答

6

一如既往,有一个built-in PHP function for this。只是在开玩笑。 =)

我见过的所有平面图都非常单调,我认为你可以用颜色和颜色饱和度来玩一个很好的猜测,就是图像是一个标志或一个平面图。

如:is the image has less than 2 or 3 colors is a floor plan.

如:if the sum/average of the saturation is less than X it's a floor plan.

黑色和白色(以及在平面图中使用其他类似的颜色)的饱和是零,或者非常接近于零,而标志往往更具视觉吸引力,因此使用更饱和的颜色。

下面是一个简单的函数来计算一个十六进制RGB颜色的饱和度:

function Saturation($color) 
{ 
    $color = array_map('hexdec', str_split($color, 2)); 

    if (max($color) > 0) 
    { 
     return (max($color) - min($color))/max($color); 
    } 

    return 0; 
} 

var_dump(Saturation('000000')); // black 0.0000000000000000 
var_dump(Saturation('FFFFFF')); // white 0.0000000000000000 
var_dump(Saturation('818185')); // grey  0.0300751879699249 
var_dump(Saturation('5B9058')); // green 0.3888888888888889 
var_dump(Saturation('DE1C5F')); // pink  0.8738738738738738 
var_dump(Saturation('FE7A15')); // orange 0.9173228346456692 
var_dump(Saturation('FF0000')); // red  1.0000000000000000 
var_dump(Saturation('80FF80')); // ---  0.4980392156862745 
var_dump(Saturation('000080')); // ---  1.0000000000000000 

使用imagecolorat()imagecolorsforindex()你可以实现一个简单的函数,环槽的所有图像和和的像素/计算饱和度的平均值。如果图像的饱和度高于您定义的自定义阈值,则可以假定图像是徽标。

有一件你不应该忘记的是,具有更高分辨率的图像通常会有更多的饱和度(更多的像素进行求和),所以为了这个算法以及为了您的服务器性能,它会是明智地将所有图像调整为通用分辨率(比如100x100或50x50)来对它们进行分类,一旦分类,您可以使用原始(未调整大小)的图像。

我与你提供的图像一个简单的测试,这里是我使用的代码:

$images = array('./44199.jpg', './68614.jpg', './95205.jpg', './logo.png', './logo.gif'); 

foreach ($images as $image) 
{ 
    $sat = 0; 
    $image = ImageCreateFromString(file_get_contents($image)); 

    for ($x = 0; $x < ImageSX($image); $x++) 
    { 
     for ($y = 0; $y < ImageSY($image); $y++) 
     { 
      $color = ImageColorsForIndex($image, ImageColorAt($image, $x, $y)); 

      if (is_array($color) === true) 
      { 
       $sat += Saturation(dechex($color['red']) . dechex($color['green']) . dechex($color['blue'])); 
      } 
     } 
    } 

    echo ($sat/(ImageSX($image) * ImageSY($image))); 
    echo '<hr />'; 
} 

而且这里的结果:

green floor plant:  0.0151028053 
black floor plant:  0.0000278867 
black and white logo: 0.1245559912 
stackoverflow logo:  0.0399864136 
google logo:   0.1259357324 

只使用这些例子中,我会形象地说是地板厂如果平均饱和度小于0.03或0.035,你可以调整通过添加额外的例子它远一点。

+0

除非是带有公司徽标的平面图:)但这也是我的方法。 +1 – 2009-12-20 17:11:12

+0

@Pekka:尽管如此,通过调整,该标志将被几乎忽略不计,并会以饱和贡献只是一些无关紧要的点。如果不是这意味着它是一个带有平面图的徽标,而不是带有徽标的平面图。 =) – 2009-12-20 17:35:29

+0

@Pekka:另外,他可以用平均值来解释这个小文物,而不是使用总和。 – 2009-12-20 17:36:19

1

我非常怀疑任何这样的工具已经存在,并创造任何准确的将是非-不重要的。如果您需要整理一组现有的图像(例如,您有一个未分类的目录),那么您可以编写一个“足够好”的工具并手动处理这些故障。如果您需要用新图像动态地执行此操作,则可能是错误的方法。

如果我为前一种情况尝试此操作,我可能会寻找一些可以用作代理的细微差别。楼层平面图通常比标识大很多(无论是文件大小还是图像大小)?平面图的颜色较少,然后是徽标?如果使用一些微不足道的东西,我可以获得75%的准确率,那么这可能是一条可行的路。

+0

+1 - 另一个简单的指标是文件名中的关键字,如“logo”或“floor”:) – 2009-12-20 08:48:29

+0

感谢您的回答,但我试过这种方法很多标识与地板尺寸相同计划。任何其他可以使用的指标?也请看到我的评论上述有关(使用房间的角落) – user235410 2009-12-20 18:34:16

+0

标志往往不是高得较宽我想您可以将图像的平面图分类的方式吗? – 2009-12-20 21:03:33

1

这样的东西 - 图像模式的识别 - 在时间上往往非常昂贵,极不可靠,并且不断需要更新和修补以匹配新案例。

我可以问你为什么要这么做?有没有在您的网站的工作流程一个地步,可以手动确定的图像是否是标志或平面图?编写一个让用户确定上传时哪个应用程序的应用程序会不会更容易?为什么首先有一组混合的数据?

+0

我从客户端获取数据作为一批未排序的图像。 因为它含有当我显示每个需要进行分类,如果可能的话自动(这样我就可以在将来使用它),我已经写了一部分(该楼盘的楼层平面图及公司徽标)图像的千以95%的准确度对属性的照片进行分类,所以现在剩下的图像中我留下了标识和平面图。 – user235410 2009-12-20 18:42:46

+1

我明白了。这已经很令人印象深刻了。不过,我认为手头的任务确实更容易出错率很高。我个人会选择一个完全手动的程序,创建一个界面,可以很容易地指向和点击什么。但是,如果你自动化 - 也许使用这里发布的一个非常有趣的建议 - 我相信很多人(包括我)会有兴趣了解它是如何实现的。 – 2009-12-20 18:53:13

1

尽管认为这是需要人工干预的事情,但您可以做的一件事是检查图像的大小。

一个小的(无论是在MB和尺寸)图像可能是一个标志。

一个大的(在MB和维度方面)图像可能是一个平面图。

但是,这只是一个概率测量,绝不是万无一失的。

该类型的图像也是一个指标,但少一个。标志是更可能是JPG,PNG或GIF,楼层平面图都可能会成为TIFF或其他无损格式 - 但不能保证。

0

正如其他人说,比如图像识别通常是可怕的复杂。忘记PHP。

不过,看在你的样品我看到一个标准的MIGHT工作得很好,如果它没有和将是很容易实现:

通过良好的OCR运行图像,看看有什么字符串弹出。如果你发现一堆描述房间或这些功能的词...

我想将图像旋转90度,然后再次尝试捕捉垂直标签。

编辑: 既然你说你试过了,它不起作用,也许你需要首先清理杂乱。基于空白切片图像。运行OCR对付每个子图像,以防万一它试图解析线条时会出现混乱。您可以使用图像编辑器手动对其进行测试以对其进行分割。

+0

试过你会推荐哪些OCR工具?我试了tesseract,它无法找出文本 – user235410 2009-12-21 06:45:57

+0

对不起,但我不能帮助工具。我还没有处理足够的OCR知道可以做什么。 – 2009-12-21 19:11:33

+0

我认为识别公司标志中的字符本身就是一项复杂的工作。 – 2009-12-22 07:44:16

2

想到的第一件事情之一是,平面图往往会有比90度更多的线条,比任何一般的标志都要多。

快速第一遍将是在图像上运行Canny edge detection,并使用Hough transform和rho,Theta定义的线对角度进行投票。如果你看到一个非常强的对应于Theta =(0,90,180,270)的rho相加,你可以将图像分类为平面图。

另一种选择是走边缘图像坎尼步骤之后只从长的,连续的线段数票,去除噪声。

+1

任何想法如何编写这样做的程序?或者,你能送我去,可以解释这个东西,所以我可以写我自己 – user235410 2009-12-23 06:32:49

0

使用两种颜色饱和度图像尺寸(无论是在以前的答案单独提出)。使用人体分类数字的大量样本,看看它们在二维空间(尺寸x饱和度)中是如何绘制的,然后决定在哪里放置边界。边界不一定是一条直线,但不要试图让所有点都适合,否则你会以牺牲新数据为代价来“记忆”样本。最好找到一个适合大多数样本的相对简单的边界,它应该适合大部分数据。

你必须容忍一定的错误。一个万无一失的解决方案是不可能的。如果我选择平面图作为我公司的标志怎么办? (这不是一个笑话,它恰恰是搞笑)

1

一个简单的没有脑子的尝试我第一次尝试是使用SVM学习从样本中获得的SIFT关键点。但在你做这件事之前,你需要标记一小部分图像,给它一个-1(平面图)或1(一个图标)。如果一幅图像有更多关键点被分类为平面图,那么它必须是一个平面布置图,如果它具有更多关键点归类为标识,那么它必须是标识。在计算机视觉领域,这被称为特征袋方法,也是最简单的方法之一。更复杂的方法可能会产生更好的结果,但这是一个好的开始。

+1

不知道如何编写一个程序,它是一个地方吗? 或者你可以送我去,可以解释这个东西的地方,所以我可以写我自己 – user235410 2009-12-23 06:25:57

+0

@tomlei:也许你可以在这个题为“关键点的包视觉分类”签出纸由Gabriella Csurka等。 – 2009-12-29 10:41:20

3

将它外包给人类可能是最容易的。

如果你有预算,考虑Amazon's Mechanical Turk。请参阅维基百科了解general description

或者,您可以自己做外包。编写一个PHP脚本来显示你的一张图片,并提示用户将它排序为“logo”我们的“平面图”。一旦你在网络服务器上运行了这个程序,就可以通过电子邮件发送你的整个办公室,并要求每个人将20张图像分类为个人喜好。

更重要的是,使之成为contest--谁排序最图像将赢得一个iPod的人!

也许最简单的,邀请大家你知道了比萨饼和啤酒,并设置了一堆的笔记本电脑,并让每个人都花几分钟的时间排序。

有一些软件方法可以完成你的任务,但是如果它是一次性活动,少于几千幅图片和至少几百美元的预算,那么比我认为你的生活可能更容易使用人类。