ここ数年で私が取り組んだ最も興味深いプロジェクトの1つは、 画像処理 に関するプロジェクトです。目標は、Coca-Cola 'cans' を認識できるようにするシステムを開発することでした(私はWordの 'cans'を強調しています。すぐにその理由がわかります)。下のサンプルを見ることができます、缶はスケールと回転で緑色の長方形で認識されます。
プロジェクトに対するいくつかの制約
だから、あなたはこのようなトリッキーなことになってしまうかもしれません(この場合私のアルゴリズムは完全に失敗しました)。
私はしばらく前にこのプロジェクトをやりました、そしてそれをすることをとても楽しんで、そして私はまともな実装をしました。これが私の実装についての詳細です:
言語 : OpenCV libraryを使用してC++で実行されます。
前処理 :画像の前処理、すなわちアルゴリズムに与えるために画像をより生の形に変換するために、2つの方法を使いました。
アルゴリズム :このタスクのために選んだアルゴリズム自体は、 これ - 特徴抽出に関する素晴らしい本で、 Generalized Hough Transform と呼ばれています - /(通常のHough変換とはかなり異なります)。それは基本的にいくつかのことを言います:
最終的には、投票のヒートマップが表示されます。たとえば、ここでは缶の輪郭のすべてのピクセルがその重心に投票するので、同じピクセルには多数の投票があります。下図のようにヒートマップにピークがあります。
それが得られたら、単純なしきい値ベースのヒューリスティックで中心ピクセルの位置を取得できます。そこからスケールと回転を導き出し、その周りに小さな長方形をプロットすることができます(最終的なスケールと回転係数は明らかにあなたの基準になります)元のテンプレート)。理論的には少なくとも...
結果 :このアプローチは基本的なケースではうまくいきましたが、次のような分野では非常に欠けていました。
4つの特定の の問題を解決するために、 排他的にOpenCV の機能を使用して、私の specific アルゴリズムを改善できますか?
結局のところ、質問をする人だけが学ぶべきではないと私は思う。 :)
代替アプローチは、 スケール不変特徴変換 (SIFT)または 高速化ロバスト特徴 (SURF)を使用して特徴(キーポイント)を抽出することです。
OpenCV 2.3.1に実装されています。
Features2D + Homographyにある既知のオブジェクトを見つけるための機能を使ったNiceコード例を見つけることができます
どちらのアルゴリズムもスケーリングと回転に対して不変です。これらは機能を扱うので、( - 十分なキーポイントが見える限り) occlusion を扱うこともできます。
画像のソース:チュートリアルの例
処理はSIFTに数百msかかり、SURFは少し速いですが、リアルタイムアプリケーションには適していません。 ORBは回転不変性に関しては弱いFASTを使用します。
作業をスピードアップするために、私はあなたが任意の画像/オブジェクトを探すのではなく、Coca-Colaのロゴのあるものを見つけるように求められているという事実を利用します。このロゴは非常に独特であり、周波数領域、特にRGBの赤チャンネルに特徴的なスケール不変のシグネチャを持つ必要があるため、これは重要です。すなわち、水平走査線(水平に整列されたロゴ上で訓練された)が遭遇する赤から白へ、赤への交互のパターンは、それがロゴの中心軸を通過するとき特有の「リズム」を有するであろう。そのリズムは、異なる縮尺と方向で「スピードアップ」または「スローダウン」しますが、それに比例して同じになります。あなたは、スターバーストパターンで、ロゴを通して水平方向と垂直方向の両方に対角線上に、そのようなスキャンラインを数十個識別/定義することができます。これらを「シグネチャスキャンライン」と呼びます。
ターゲット画像内でこのシグネチャを検索することは、画像を水平方向のストリップでスキャンするという簡単なことです。赤チャンネルの高周波数を探し(赤の領域から白の領域への移動を示します)、一度見つけたら、それに続いてトレーニングセッションで識別された周波数リズムの1つがあるかどうかを確認します。一致が見つかると、スキャンラインのロゴの向きと位置がすぐにわかります(トレーニング中にそれらのことを追跡している場合)ので、そこからロゴの境界を識別するのは簡単です。
これが線形に効率的なアルゴリズムではない場合、またはそれに近い場合、私は驚きます。それは明らかにあなたの缶詰の差別に対処していませんが、少なくともあなたはあなたのロゴを持っているでしょう。
(更新:ボトル認識のためにロゴに隣接するコークス(茶色の液体)を探します - つまり、insideボトル)。あるいは、空のボトルの場合は、capは基本的な形状、サイズ、ロゴからの距離が常に同じで、通常は白または赤になりますcap =ロゴはロゴを基準にしたもの)もちろん絶対確実というわけではありませんが、ここでの目標はeasyones fast)を見つけることです。
(私の画像処理の日から数年が経ったので、この提案を高レベルで概念的なものにしておきました。人間の目がどのように動作するか、あるいは少なくとも私の脳がどのように動作するかをおおよそ示すと思います)
おもしろい問題:あなたのボトルのイメージをちらっと見たとき、私はそれも缶だと思った。しかし、人間として、私が違いを言うために私がしたのはそれからそれがボトルでもあることに気づいたということです...
それで、缶とボトルを区別するために、最初にボトルをスキャンするだけではどうでしょうか。見つかった場合は、缶を探す前にラベルを覆い隠してください。
あなたが既に缶をやっているなら、実装するのはそれほど難しくありません。本当のマイナス面は、処理時間が2倍になることです。 (しかし、実際のアプリケーションを考えてみると、とにかくボトルを使いたがることになるでしょう;-)
(ボトルの透明な部分が隠れているという条件で)2番目の画像で人間がボトルと缶を区別するのは難しいことではありませんか。
それらは非常に小さい領域を除いてほとんど同じです(つまり、缶の上部の幅は少し小さいですが、ボトルのラッパーは全体を通して同じ幅ですが、マイナーな変更は正しいですか?)
私の頭に浮かんだ最初のことはボトルの赤いトップをチェックすることでした。しかし、ボトルのトップがない場合、またはボトルが部分的に隠されている場合(上記のように)、それはまだ問題です。
私が考えた第二のことは、ボトルの透明度についてでした。 OpenCVには、画像内の透明なオブジェクトを見つけるためのいくつかの作業があります。以下のリンクを確認してください。
特にこれを見て、ガラスをどの程度正確に検出しているかを確認します。
それらの意味付けの結果を参照してください。
彼らはそれが論文の実装であると言っています K. McHenryとJ. Ponceによる「ガラスを見つけるための測地線アクティブ輪郭フレームワーク」、CVPR 2006 。
あなたの場合は少し役に立つかもしれませんが、ボトルがいっぱいになると問題が発生します。
だから私はここで考える、あなたは最初にボトルの透明なボディを探すか、横方向に二つの透明なオブジェクトにつながっている赤い領域を探すことができます。それは明らかにボトルです。 (理想的に作業するときは、次のような画像になります。)
これで黄色い領域、つまりボトルのラベルを削除し、アルゴリズムを実行して缶を見つけることができます。
とにかく、この解決策も他の解決策のように異なる問題を抱えています。
しかし、とにかく、写真に上記の問題がない場合は、これはより良い方法です。
私は本当にこの問題に Darren Cook's と スタッカーの答え が好きです。私は自分の考えをそれらについてのコメントに投げ入れている最中にいましたが、私のアプローチはここにとどまらないほど回答的な形をしていると思います。
手短に言えば、Coca-Colaのロゴが空間の特定の場所に存在することを確認するためのアルゴリズムを特定しました。あなたは今、任意の向きと任意の倍率について、Coca-Cola cans を他のオブジェクトと区別するのにふさわしい発見的方法を決定しようとしています: bottle 、 billboards 、 広告 、および Coca-Cola paraphernalia このアイコンのロゴにすべて関連付けられています。あなたはあなたの問題声明の中でこれらの追加のケースの多くを指摘しなかった、しかし私はそれらがあなたのアルゴリズムの成功に不可欠であると思う。
ここでの秘密は、a can にどんな視覚的特徴が含まれているか、または否定的なスペースを通して、缶には存在しない他のCoke製品にどのような特徴が存在するかを決定することです。そのために、 現在の最上位の回答 は、ボトルキャップ、液体、またはその他の類似のビジュアルの存在によって、「ボトル」が識別されない場合に限り「缶」を選択するための基本的なアプローチを示しますヒューリスティック.
問題はこれが故障することです。たとえば、ボトルが空になってキャップがなくて誤検知につながる可能性があります。あるいは、 部分的なボトル 追加の機能が壊されている可能性があり、これもまた誤検出につながります。言うまでもなく、これはエレガントではありませんし、私たちの目的にも効果的ではありません。
このためには、缶の最も正しい選択基準は次のようになります。
分類は次のようになります。
これは、検出されたものをユーザーに視覚的に強調し、正しくない方法で、誤った缶詰として検出される可能性のある弱い肯定を強調します。
各プロパティの検出には非常に異なる時間と空間の複雑さがあり、アプローチごとに http://dsp.stackexchange.com をすばやく通過させるのが最も正確で効率的なものを判断するには合理的ですあなたの目的のためのアルゴリズム。ここでの私の意図は、純粋にそして単純に、 候補の検出空間のごく一部を無効にすることによって何かが可能かどうかを検出することです は、この問題に対する最も堅牢または効果的な解決策ではありません。それに応じて適切な行動をとるべきです。
おお、おめでとうございます。{ Hacker Newsの投稿! _全体的に見て、これは受け取った宣伝に値するかなり素晴らしい質問です。 :)
形を見る
缶/ボトルの赤い部分の形をした杖を持って行きます。ボトルのラベルが真っ直ぐなのに対し、缶は一番上で少し先細になっていることに注意してください。あなたはそれの長さにわたって赤い部分の幅を比較することによって、これら二つを区別することができます。
ハイライトを見る
ボトルと缶を区別する1つの方法は素材です。ボトルはプラスチック製で、缶はアルミ製です。十分に明るく照らされている状況では、スペキュラリティを見ることは缶ラベルからボトルラベルを伝える1つの方法です。
私が言うことができる限り、それは人間がラベルの2つのタイプの間の違いをどのように言うかということです。照明条件が悪い場合、とにかく2つを区別することには不確実性があるはずです。その場合は、透明/半透明のボトル自体の存在を検出できなければなりません。
Zdenek Kalalの 捕食者追跡装置 をご覧ください。それはいくらかの訓練を必要とします、しかしそれは追跡された対象がどのように異なる向きとスケールを見てそしてリアルタイムでそれをするかを積極的に学ぶことができます!
ソースコードは彼のサイトで入手可能です。これは _ matlab _ にありますが、おそらくコミュニティのメンバーによって既に行われたJava実装があります。 TLDのトラッカー部分をC#で正常に再実装しました。正しく覚えていれば、TLDはFernsをキーポイント検出器として使用しています。トラッカーによって失われたオブジェクトを再取得するには、代わりにSURFまたはSIFT(@stackerによって既に提案されています)を使用します。トラッカーのフィードバックは、時間とともに非常に高い精度でオブジェクトを再取得することを可能にするsift/surfテンプレートの動的リストを時間とともに構築することを容易にします。
私のC#のトラッカー実装に興味があるなら、遠慮なく聞いてください。
あなたがあなたの制約の一つではなかったカメラだけに限定されないならば、おそらくあなたはXbox Kinect のような距離センサーを使うことに移ることができます。これを使用して、画像の奥行きと色に基づく一致セグメンテーションを実行できます。これにより、画像内のオブジェクトをより速く分離することができます。缶の外形や色だけではなく、缶の形状を一致させるためにICPマッチングまたは類似の手法を使用することができます。これが円筒形である場合、これはターゲットの3Dスキャンがある場合に有効です。これらのテクニックは、スピードの問題を解決するような特定の目的のために使用された場合は特に非常に速くなります。
また、正確さやスピードのためには必ずしも必要ではありませんが、楽しみのために、色相セグメント化された画像上で訓練されたニューラルネットワークを使用して缶の形状を識別することもできます。これらは非常に高速で、多くの場合80/90%まで正確になります。各イメージで缶を手動で識別する必要があるため、トレーニングは少し時間がかかります。
私は赤い長方形を検出するでしょう:RGB - > HSV、フィルター - >バイナリイメージ、 閉じる (matlabではimclose
として知られています)
それから四角形を最大から最小まで見ます。既知の位置/スケールで小さい方の長方形を持つ方形は両方とも削除できます(ボトルの比率が一定であると仮定すると、小さい方の方がボトルキャップになります)。
これはあなたに赤い長方形を残すでしょう、そしてあなたはそれらが赤い長方形であるかコーラ缶であるかどうか言うためにどういうわけかロゴを検出する必要があります。 OCRに似ていますが、ロゴはわかっていますか?
これは非常に素朴な考えかもしれませんが(あるいはまったく機能しないかもしれませんが)、すべてのコークス缶の寸法は固定されています。同じ画像に缶とボトルの両方が含まれている場合は、サイズを考慮してそれらを区別することができます(ボトルはもっと大きくなります)。深さが足りないため(3Dマッピングから2Dマッピングへ)、ボトルが縮小して表示され、サイズに違いがない可能性があります。 ステレオイメージング を使用して深さ情報をいくつか復元してから、元のサイズを復元することができます。
うーん、私は実際に何かに興味があると思う(これはこれまでで最も興味深い質問のようなものです-だから、「完璧な」答えを見つけようとしないのは残念です、許容できるものが見つかったとしても)...
ロゴが見つかったら、問題は半分完了です。次に、ロゴとaroundの違いを把握するだけです。さらに、できる限り余分なことを行いません。これは実際にこの簡単な部分だと思います...
ロゴの周りにはとは何ですか?缶については、照明の効果にもかかわらず、基本的な色がまったく変わらない金属を見ることができます。ラベルの角度がわかれば、そのすぐ上にあるものを知ることができるので、これらの違いを見ています。
ここでは、ロゴの上と下は完全に暗く、色は一貫しています。その点で比較的簡単です。
ここでは、上と下は明るいですが、色は一貫しています。それはすべて銀色であり、すべて銀色の金属は一般的に銀色と同様、実際にはかなり珍しいようです。さらに、それは細いスリッターであり、既に識別されている赤に十分近いため、その全長にわたってその形状をトレースして、缶の金属リングとみなすことができるものの割合を計算できます。実際、缶のどこにでもそれがその一部であることを伝えるために必要なのはほんの一部だけですが、それでも、背後に金属が入った空のボトルではないことを保証するバランスを見つける必要があります。
そして最後に、トリッキーなもの。しかし、それほど難しいことではありません。赤いラッパーの真上(および真下)に見えるものだけを見て回ってください。その透明性は、背後にあるものをすべて表示することを意味します。その背後にあるものは、缶の銀の円形の金属ほど色が一貫していない可能性が高いため、それは良いことです。その背後にはさまざまなものがあり、空の(または透明な液体で満たされた)ボトル、または一貫した色であることがわかります。これは、液体で満たされているか、単にボトルの前にあることを意味しますソリッドカラー。上部と下部に最も近いものを使用しているため、適切な色が適切な場所に配置される可能性は比較的低くなります。缶の重要な視覚的要素がなく、ボトルの背後にあるものに比べて比較的単純であるため、ボトルであることがわかります。
(最後の1つが空の大きなコカコーラボトルで見つけることができた最高のものでした-興味深いことに、キャップとリングは黄色で、キャップの赤みはおそらく頼るべきではないことを示しています)
プラスチックの抽象化の後でも、同様の銀色がボトルの背後にあるというまれな状況、またはボトルが何らかの形で同じ銀色の液体で満たされている場合、大まかに見積もることができるものに頼ることができます銀の形-私が言ったように、それは円形で、缶の形に従います。しかし、画像処理に関する特定の知識が不足していても、それは遅いように思えます。さらに良いのは、ロゴのsidesを一度確認して、そこに同じ銀色のものがないことを確認して、これを推測してみませんか?ああ、でも缶の後ろに同じ色合いの銀があるとどうなる?それから、缶の上部と底部をもう一度見て、形状にもっと注意を払う必要があります。
これがどれほど完璧であるかに応じて、それは非常に遅いかもしれませんが、私の基本的な概念は最初に最も簡単で最も近いものをチェックすることだと思います。他の要素の形状を計算する作業に進む前に、すでに一致した形状(とにかくこれの最も些細な部分であるように見える)の周りの色の違いを調べます。リストするには、次のようになります。
これができない場合は、おそらく缶の上部と底部が覆われていることを意味し、缶とボトルを確実に区別するために人間が使用できた可能性のある唯一のものは、閉塞と反射です缶の、それは多く処理するのが難しい戦いになります。ただし、さらに進むには、他の回答で述べた半透明のスキャン技術を使用して、缶/ボトルの角度をたどって、よりボトルのような特徴を確認することができます。
興味深い追加の悪夢には、ラベルの上下に金属がたまたま見える距離でボトルの後ろに都合よく座っている缶が含まれる場合がありますが、赤の全長に沿ってスキャンしている限り失敗しますラベル-缶を含む缶を実際に検出しているのとは対照的に、缶を実際に検出しているのではなく、缶を検出していないため、これは実際により大きな問題です。その場合、ガラスは半分空です!
免責事項として、私はこの質問以外の画像処理の経験はなく、これまで考えたこともありませんが、非常に興味深いので、それについてかなり深く考えるようになり、他のすべての答えを読んだ後、これはおそらく最も簡単なandそれを実現する最も効率的な方法。個人的には、実際にこれをプログラミングすることを考える必要がないのはうれしいです!
編集
さらに、私がMSペイントで行ったこの図面を見てください。それは絶対にひどく不完全です。しかし、形状と色だけに基づいて、おそらくどうなるか推測できます。本質的に、これらはスキャンを煩わせる必要がある唯一のものです。その非常に特徴的な形と色の組み合わせを非常に近くで見ると、他にどんなものがあるのでしょうか?私がペイントしなかったビット、白い背景は、「一貫性のないもの」とみなされるべきです。背景が透明な場合、他のほとんどの画像を覆い隠すことができます。
私はOpenCVに気付いていませんが、問題を論理的に見て、あなたが探している画像を変えることによってボトルと缶を区別することができると思います、すなわちCoca Cola。缶の場合のように、コカコーラの上部に銀の裏地があり、ボトルの場合にはそのような銀の裏地がないように、缶の上部まで組み込む必要があります。
しかし、明らかにこのアルゴリズムは缶の上が隠されている場合には失敗しますが、そのような場合には人間でさえ両者を区別することはできません(ボトル/缶のコカコーラ部分だけが見える場合)
私は挑戦が好きで、問題を解決する答えを出したかったと思います。
上限の検出は別の問題です。それは複雑でも単純でもかまいません。私があなただったら、単純な決定のためにROIのカラーヒストグラムをチェックするだけです。
間違っている場合は、フィードバックをお願いします。ありがとう。
あなたは経験から有機的に分類精度を学びそして改善するプログラムを必要としています。
私はディープラーニングをお勧めします。ディープラーニングでは、これは些細な問題になります。
Tensorflowでインセプションv3モデルを再訓練することができます。
新しいカテゴリーのためにインセプションの最終レイヤーを抑制する方法 。
この場合、畳み込みニューラルネットワークを訓練して、オブジェクトをコカコーラの缶かそうでないかに分類します。
この質問に答えるのに数年遅れています。過去5年間で最先端の技術がCNNによって限界に近づいていたので、私は今このタスクを行うためにOpenCVを使用しません。 (私はあなたが質問にOpenCvの機能を特に望んでいたことを知っています)Faster-RCNN、YOLO、SSDなどのオブジェクト検出アルゴリズムはOpenCVの機能と比べてかなりのマージンでこの問題を解決するでしょう。私が今この問題に取り組むなら(6年後に!!)私は間違いなくFaster-RCNNを使います。
オブジェクトを認識するために使用されるたくさんの色記述子があります、以下の紙はそれらの多くを比較します。 SIFTやSURFと組み合わせると特に強力です。彼らは多くの関心点を認識していないので、SURFやSIFTだけでは、コカコーラがイメージを作るのにあまり役に立ちません、あなたは助けるために色情報が必要です。プロジェクトではSURFとBIC(Border/Interior Pixel Classification)を使用していますが、オブジェクトを認識するのに役立ちました。
トピック外かどうかにかかわらず、私はあなたの質問が好きです。P
ちょっとおもしろい。私はロボット工学とコンピュータビジョンをカバーした私の学位の科目を完成させたばかりです。学期のための私達のプロジェクトはあなたが説明するものと非常に似ていました。
Xbox Kinectを使用してさまざまな照明や環境条件であらゆる方向のコークスボトルや缶を検出するロボットを開発する必要がありました。我々の解決策は、ハフサークル変換と組み合わせて色相チャネル上でバンドパスフィルタを使用することを含んでいた。私たちは環境を少し拘束することができました(ロボットとKinectセンサーをどこにどのように配置するかを選ぶことができました)。
私たちのアプローチについては で私のブログ投稿を読むことができます :)
ディープラーニング
コーラ缶を含む少なくとも数百枚の画像を集め、それらの周りの境界ボックスに陽性クラスとして注釈を付け、コーラの瓶および他のコーラ製品にそれらに陰性クラスならびにランダムなオブジェクトのラベルを付ける。
非常に大きなデータセットを収集しない限り、小さなデータセットに対して詳細な学習機能を使用するというトリックを実行してください。 Support Vector Machines(SVM)とディープニューラルネットの組み合わせを使用するのが理想的です。
分類を行うためにニューラルネットワークの決定(最終)レイヤを使用する代わりに、画像を以前に学習されたディープラーニングモデル(例えば、GoogleNet)に供給したら、分類子を訓練するための特徴として前のレイヤのデータを使用する。
OpenCVとGoogle Net: http://docs.opencv.org/trunk/d5/de7/tutorial_dnn_googlenet.html
OpenCVとSVM: http://docs.opencv.org/2.4/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html
これらすべてのNiceソリューションに代わるものとして、独自の分類子を訓練し、アプリケーションをエラーに強くすることができます。たとえば、 Haar Training を使用すると、ターゲットのポジティブイメージとネガティブイメージを大量に提供できます。
缶のみを抽出することは有用であり得、そして透明物体の検出と組み合わせることができる。
MVTec からHALCONと呼ばれるコンピュータビジョンパッケージがあります。デモモードで実行してからコード内の演算子を調べて、既存のOpenCV演算子からそれらを実装する方法を見ることができる、あなたの問題に似たたくさんの例があります。
このパッケージを使って、このような問題の複雑なアルゴリズムを素早くプロトタイプし、次に既存のOpenCV機能を使ってそれらを実装する方法を見つけます。特にあなたの場合には、演算子 find_scaled_shape_model に埋め込まれた機能をOpenCVに実装することを試みることができます。 OpenCVで似たようなことをする方法を見つけるのを助けることができるアルゴリズム実装に関する科学論文を指摘するオペレータもいます。お役に立てれば...
私が最初に探すのは色です - 画像の中で赤目検出をするとき、赤のように - 検出するための特定の色の範囲があります。確かに画像に表示されます。
1:第一の特徴は色であり、そして赤が非常に支配的である。コカ・コーラレッドを検出した後、興味のある項目がいくつかあります。1A:この赤い領域の大きさ(本当の缶かどうかを判断するのに十分な量ですか?10ピクセルではおそらく不十分)ラベルの色 - 「コカコーラ」または波。 1B1:それがラベルである可能性が高いと考えるのに十分なものがありますか。
項目1は一種の近道です - それがその画像に存在しない場合の前処理 - 次に進みます。
もしそうなら、私はそれから私のイメージのそのセグメントを利用して、問題となっている領域からもう少しズームアウトして見始めることができます - 基本的に周囲の領域/エッジを見てください...
2:1で上記の画像領域IDが与えられた場合、問題のアイテムの周囲の点[辺]を確認します。 A:缶の上や下の銀のように見えるものはありますか? B:瓶は透明に見えるかもしれませんが、ガラステーブルもそうかもしれません - ガラステーブル/棚や透明な領域があります - そうであれば複数の可能なアウトがあります。ボトルMIGHTには赤いキャップが付いていますが、そうではないかもしれませんが、ボトルのトップ/ネジの形、またはキャップのどちらかがあるはずです。 C:これがAとBに失敗したとしても、それはまだ部分的な可能性があります。部分的なボトル/部分的な缶は同じに見えるかもしれないので、これは部分的なときより複雑です。小さなボトルのサイズは似ているかもしれません。
3:上記の分析の後、レタリングとwaveのロゴを見てみましょう。なぜなら、私は言葉の中のいくつかの文字を探すことができるからです。できれば、波はテキストの特定の点(距離方向)に整列するので、その確率を検索して、距離xの波のその点にどの文字があるべきかを知ることができます。
これは私が取り組んだ古いプロジェクトです。 MAP画像はJavaScriptで非常に使いやすいです。私はあなたにそのオブジェクトを提供し、あなたはそれを読みそしてそれを使う方法を知っている。 MAP画像を使用するためにJQueryや他のシステムを必要としません。
//Copyright Cherif yahiaoui, by ELEBAN.FR
//variables de flottement.
var myInstOne = null;
var globalize = null;
var eleban_preload_images = function (name, imgs, url){
try{
var oThis = this;
this.images = new Array();
this.imageshover = new Array();
this.imagesNames = new Array(imgs.split(";"));
for(var i=0; i < this.imagesNames[0].length; i++){
this.images[i] = new Image();
this.imageshover[i] = new Image();
}
this.url = url;
this.GetAbsoluteurl = function () {
var img = new Image(); img.src = url;
url = img.src; img = null;
this.url = url;
};
this.Preload = function () {
for(var i=0; i < this.imagesNames[0].length; i++){
this.images[i].src = this.url+("btn-"+this.imagesNames[0][i]+".png");
this.imageshover[i].src = this.url+("btn-"+this.imagesNames[0][i]+"-hover.png");
}
};
this.GetAbsoluteurl();
this.Preload();
}
finally {return;}
}
var g_preloaderhover = new eleban_preload_images("loaderhover","menu;malette;reservation;cabine;facebook;map;amis","./images/");
//variable arret flottement
var g_stopflo = false;
var myObjfloater = function(name, idname, itop, differ ) {
var oThis = this; // création d'une référence vers l'objet courant
this.name = name;
this.id =idname;
this.xstep= 0.3;
this.itime = 30;
this.obj = null;
this.y = itop;
this.yadd = 0;
this.up = true;
this.pause = false;
this.differ = differ;
this.coordsimage = null;
this.objimg = null;
this.initimages = false;
this.compteur = 0;
this.over = false;
this.timeoutstop = null;
try{
this.initimage = function(){
var img = this.obj.getElementsByTagName('img')[0];
this.coordsimage = new Array(img.width, img.height);
this.objimg = img;
this.initimages = true;
};
this.myMethod = function() {
if(!g_stopflo){
if(this.differ != 0){
this.differ=this.differ-0.1;
}else{
if(this.obj){
if(this.over == false){
this.yadd=this.yadd+0.1; this.itime = this.itime + 10;
this.obj.style.visibility = "hidden";
this.y = ((this.up)? this.y - this.yadd : this.y + this.yadd);
this.obj.style.marginTop = this.y +"%" ;
this.obj.style.visibility = "visible";
if (this.yadd > this.xstep){
this.up = (this.up)? false : true;
this.yadd = -0.1; this.itime=180;
}
}
}else{
if (document){
if(document.getElementById) {
this.obj = document.getElementById(this.id);
//this.y = this.obj.offsetTop;
}else{
if(document.getElementByTagName) { this.obj = document.getElementByTagName(this.id); this.y = this.obj.offsetTop;}
}
}
}
}
this.timeoutstop=setTimeout(function() { oThis.myMethod(); }, this.itime);
}
};
this.callDelayed = function() {
// utilisation de la référence vers l'objet
if(!g_stopflo){
this.timeoutstop=setTimeout(function() { oThis.myMethod(); }, this.itime);
}
};
}
finally {return;}
};
// special creation des zones AREA
function eleban_createallarea(){
try{
var measur = new Array("w", "h");
measur["w"] = new Array(330,570,185,300,115,390,225);
measur["h"] = new Array(460,570,295,450,100,190,115);
var ititle = new Array("Voir les menus et nos suggestions","Repas à emporter","Réservation d’une table","Nous contacter","Nous rejoindre sur FaceBook","Calculer votre trajet","liste des amis");
var ihref = new Array("menus.html","emporter.html","reservation.html","contact.html","likebox.html","google.html","amis.html");
var b_map = new Array(0,1,2,3,4,5,6);
b_map[0] = "71,32,240,32,249,43,289,352,280,366,102,385,90,371,51,38";
b_map[1] = "66,52,95,14,129,56,115,91,100,93,112,273,128,284,122,366,176,343,193,296,191,194,147,189,145,166,201,111,199,84,545,105,532,354,509,388,412,478,32,401,77,383,87,375,82,286,95,269,94,221,24,195,11,165,9,120,89,123,89,94,78,92,77,92,77,93,75,93,77,93,76,93,79,92";
b_map[2] = "19,25,169,38,173,112,161,113,105,103,90,125,91,262,121,269,124,281,96,293,62,289,49,281,56,268,83,264,84,121,71,98,16,90";
b_map[3] = "60,0,216,1,226,20,225,403,168,421,42,410,45,10";
b_map[4] = "31,7,72,10,82,18,88,45,88,71,76,81,29,80,17,68,16,18";
b_map[5] = "91,40,141,38,178,27,184,4,211,5,223,24,240,23,386,135,229,121,103,180,6,156,49,94";
b_map[6] = "6,32,69,18,79,6,118,7,141,2,149,10,211,17,202,28,209,30,189,62,195,70,178,74,180,90,164,90,154,107,68,101,34,104,34,98,18,97,28,84,15,84,30,65";
if (document.getElementById){
for (var i=0; i<b_map.length;i++){
var obj = document.getElementById("pc_menu"+i);
if(obj){
var ct = '<img class=\"pc_menu\" src=\"'+g_preloaderhover.images[i].src+'\" alt=\"\" width=\"'+measur["w"][i]+'\" height=\"'+measur["h"][i]+'\" usemap=\"#MAP_INDEX'+i+'\" \/>';
ct+='<map name=\"MAP_INDEX'+i+'\">';
ct+='<area shape=\"poly\" coords=\"'+b_map[i]+'\" title=\"'+ititle[i]+'\" href=\"'+ihref[i]+'\" \/>';
ct+='<\/map>';
obj.innerHTML = ct;
}
}
}
}
finally {return;}
}
//preload, creation et gestion de tous les evenements
var image_resizer = function(g_layer){
b_org_Elm = new Array("w", "h");
b_org_Elm["w"] = new Array(330,570,185,300,115,390,225);
b_org_Elm["h"] = new Array(460,570,295,450,100,190,115);
b_map = new Array(0,1,2,3,4,5,6);
b_map[0] = new Array(71,32,240,32,249,43,289,352,280,366,102,385,90,371,51,38);
b_map[1] = new Array(66,52,95,14,129,56,115,91,100,93,112,273,128,284,122,366,176,343,193,296,191,194,147,189,145,166,201,111,199,84,545,105,532,354,509,388,412,478,32,401,77,383,87,375,82,286,95,269,94,221,24,195,11,165,9,120,89,123,89,94,78,92,77,92,77,93,75,93,77,93,76,93,79,92);
b_map[2] = new Array(19,25,169,38,173,112,161,113,105,103,90,125,91,262,121,269,124,281,96,293,62,289,49,281,56,268,83,264,84,121,71,98,16,90);
b_map[3] = new Array(60,0,216,1,226,20,225,403,168,421,42,410,45,10);
b_map[4] = new Array(31,6,70,10,78,18,84,23,88,44,88,70,78,80,75,81,33,82,23,76,18,69,16,22,21,13);
b_map[5] = new Array(91,40,141,38,178,27,184,4,211,5,223,24,240,23,386,135,229,121,103,180,6,156,49,94);
b_map[6] = new Array(6,32,69,18,79,6,118,7,141,2,149,10,211,17,202,28,209,30,189,62,195,70,178,74,180,90,164,90,154,107,68,101,34,104,34,98,18,97,28,84,15,84,30,65);
b_layer = g_layer;
//gere mouseover
this.mouseover = function(e){
if (!e) var e = window.event;
var tg = (window.event) ? e.srcElement : e.target
if (tg.nodeName){
if(tg.nodeName == "AREA"){
var divpar = (tg.parentNode)? tg.parentNode.parentNode : tg.parentElement.parentElement;
if (divpar){
if(divpar.nodeName == "DIV"){
var iiobjimg = divpar.getElementsByTagName('img');
if (iiobjimg){
ii = parseInt(divpar.id.substring(divpar.id.length-1,divpar.id.length));
iiobjimg[0].src = g_preloaderhover.imageshover[ii].src;
}
}
}
}
}
};
//gere mouseout
this.mouseout = function(e){
if (!e) var e = window.event;
tg = (window.event) ? e.srcElement : e.target
if (tg.nodeName){
if(tg.nodeName == "AREA"){
divpar = (tg.parentNode)? tg.parentNode.parentNode : tg.parentElement.parentElement;
if (divpar){
if(divpar.nodeName == "DIV"){
var iiobjimg = divpar.getElementsByTagName('img');
if (iiobjimg){
ii = parseInt(divpar.id.substring(divpar.id.length-1,divpar.id.length));
iiobjimg[0].src = g_preloaderhover.images[ii].src;
}
}
}
}
}
};
//ajout evenements entree sortie à la page web lors du chargement de la page
this.init = function () {
for(var i=0; i<b_org_Elm["w"].length;i++){
w = document.getElementById("pc_menu"+i).offsetWidth;
h = document.getElementById("pc_menu"+i).offsetHeight;
xa = w/parseFloat(b_org_Elm["w"][i]);
ya = h/parseFloat(b_org_Elm["h"][i]);
area = document.getElementById("pc_menu"+i).getElementsByTagName('area')[0];
b_map2 = area.coords.split(",");
yswitch = true;
for(m=0; m<b_map2.length;m++){
b_map2[m] = Math.round(parseFloat(b_map[i][m]) * ((yswitch)? xa: ya));
yswitch = (yswitch)? false : true;
}
area.coords = b_map2.join(',');
}
};
this.resize = function () {
clearTimeout(myInstOne.timeoutstop);
g_stopflo=true;
globalize.init();
g_stopflo=false;
myInstOne.obj = null;
myInstOne.callDelayed();
};
nar = document.getElementsByTagName('area').length;
for(var i=0; i<nar;i++){
var elem = document.getElementsByTagName('area')[i];
if (elem.addEventListener){
elem.addEventListener("onmouseover",this.mouseover,true);
elem.addEventListener("onmouseout",this.mouseout,true);
}else if (elem.attachEvent) {
elem.attachEvent("onmouseover", this.mouseover);
elem.attachEvent("onmouseout", this.mouseout);
}else{
elem["onmouseover"] = this.mouseover;
elem["onmouseout"] = this.mouseout;
}
}
window.onresize = this.resize;
window.onmouseover = this.mouseover;
window.onmouseout = this.mouseout;
}
//permet de temporiser et éviter les erreurs de chargement des objets
function temporise_Init(Lastdiv){
if(document.getElementById){
if(document.getElementById(Lastdiv)){
eleban_createallarea();
myInstOne = new myObjfloater('b_menumap11', 'pc_menu1', 1, 0);
globalize = new image_resizer(document.getElementById('pc_redim'));
globalize.init();
globalize.resize();
}else{
setTimeout(temporise_Init(Lastdiv), 30);
}
}
}
window.onload = function () {
temporise_Init("pc_bandeau");
}
あなたがそれがリアルタイムであることに興味があるならば、あなたが必要とするものは何がヘビーデューティーなものでスキャンされるかを決定するために前処理フィルタを追加することです。コカコーラである可能性が高いものをスキャンしてより確実なものに移すことができるようになる、高速で非常にリアルタイムの前処理フィルタは、次のようなものです。あなたのコカコーラの缶のsqrt(pow(red,2) + pow(blue,2) + pow(green,2))
から一定の許容範囲である色の。非常に厳密な色の許容範囲から始めて、より緩やかな色の許容範囲にあなたの方法を取りなさい。そして、あなたのロボットが現在のフレームを処理するために割り当てられた時間を使い果たしたとき、あなたの目的のために現在見つけられているボトルを使います。 sqrt(pow(red,2) + pow(blue,2) + pow(green,2))
でRGBカラーを微調整して正しく表示されるようにする必要があります。
また、これは本当に愚かに思えますが、Cコードをコンパイルしたときに-oFast
コンパイラ最適化を必ずオンにしましたか。
多分遅すぎるかもしれませんが、それでも試してみるべき理論です。
ボトル/缶の全体寸法に対する赤いロゴ領域の四角形の境界の比率は異なります。缶の場合は、1:1にする必要がありますが、ボトルの場合は異なります(キャップの有無にかかわらず)。これにより、両者を区別しやすくなります。
更新:ロゴ領域の水平方向の曲率は、それぞれのサイズの違いにより、缶とボトルの間で異なります。あなたのロボットが缶/ボトルを拾う必要があるならば、これは特に役に立つかもしれません、そしてあなたはそれに応じてグリップを決めます。