画像処理:「コカ・コーラ缶」認識のためのアルゴリズムの改善


1658

私が過去数年間取り組んだ最も興味深いプロジェクトの1つは、画像処理に関するプロジェクトでした。目標は、コカコーラの「缶」を認識できるシステムを開発することでした(「缶」という言葉を強調していることに注意してください。その理由はすぐにわかります)。下のサンプルを見ることができます。缶はスケールと回転で緑色の長方形で認識されます。

テンプレートマッチング

プロジェクトに関するいくつかの制約:

  • 背景は非常に騒々しいかもしれません。
  • 缶は、任意の可能性があり、スケールまたは回転(合理的な範囲内で)、あるいは配向を。
  • 画像にある程度のぼやけがある可能性があります(輪郭が完全にまっすぐではない場合があります)。
  • 画像にコカコーラのボトルが含まれている可能性があり、アルゴリズムは缶を検出するだけです!
  • 画像の明るさは大きく異なる可能性があります(そのため、色の検出に「過度に」依存することはできません)。
  • 缶は、部分的側面または途中に隠された、おそらく一部は瓶の後ろに隠れてすることができます。
  • 画像にはまったくがありません。その場合、何も見つからず、そのことを伝えるメッセージを書く必要がありました。

したがって、次のようなトリッキーなものになる可能性があります(この場合、アルゴリズムが完全に失敗しました)。

完全に失敗

私はこのプロジェクトを少し前にやっていましたが、それを行うのはとても面白かったし、適切な実装がありました。ここに私の実装に関するいくつかの詳細があります:

言語OpenCVライブラリを使用してC ++で実行。

前処理:画像の前処理、つまり画像をより生の形式に変換してアルゴリズムに提供するために、2つの方法を使用しました。

  1. カラードメインをRGBからHSVに変更し、「赤」の色相に基づいてフィルタリングし、特定のしきい値を超える彩度でオレンジ色のような色を避け、低い値でフィルタリングして暗い色調を避けます。最終結果は、白黒のバイナリ画像で、すべての白いピクセルがこのしきい値に一致するピクセルを表します。明らかに画像にはまだがらくたがたくさんありますが、これにより、操作する必要がある次元の数が減ります。 2値化画像
  2. ノイズを減らすために、メディアンフィルタリング(すべての近傍のピクセル値の中央値を取り、この値でピクセルを置き換える)を使用したノイズフィルタリング。
  3. キャニーエッジ検出フィルターを使用して、前の2つの手順の後にすべてのアイテムの輪郭を取得します。 輪郭検出

アルゴリズム:このタスクで選択したアルゴリズム自体は、特徴抽出に関するこの素晴らしい本から引用され、一般化ハフ変換(通常のハフ変換とはかなり異なります)と呼ばれています。それは基本的にいくつかのことを言います:

  • 分析方程式(ここではその場合)を知らなくても、空間内のオブジェクトを記述できます。
  • スケーリング係数と回転係数のすべての組み合わせについて画像を基本的にテストするため、スケーリングや回転などの画像変形に耐性があります。
  • アルゴリズムが「学習」する基本モデル(テンプレート)を使用します。
  • 輪郭画像に残っている各ピクセルは、モデルから学んだことに基づいて、オブジェクトの(重力に関して)中心となる別のピクセルに投票します。

最後に、投票のヒートマップが作成されます。たとえば、ここでは、缶の輪郭のすべてのピクセルがその重心に投票するので、同じピクセルに対応する多数の投票が中央にあり、ヒートマップに次のようなピークが表示されます。

GHT

それができたら、単純なしきい値ベースのヒューリスティックが中心ピクセルの位置を提供し、そこからスケールと回転を導き出し、その周りに小さな長方形をプロットできます(最終的なスケールと回転係数は明らかに、元のテンプレート)。理論的には少なくとも...

結果:現在、このアプローチは基本的なケースでは機能しましたが、一部の領域では非常に不十分でした。

  • それは非常に遅いです!私はこれを十分に強調していません。一部の缶が非常に小さかったため、回転と平行移動のスケーリング係数が非常に高かったため、30枚のテスト画像の処理にはほぼ1日が必要でした。
  • ボトルが画像内にあると完全に失われ、何らかの理由でほとんどの場合、缶の代わりにボトルが見つかりました(おそらく、ボトルが大きく、ピクセルが多く、投票数が多かったためです)。
  • 投票は中央付近のランダムな場所のピクセルで行われ、非常にノイズの多いヒートマップで終わったため、あいまいな画像も良くありませんでした。
  • 平行移動と回転の不変が達成されましたが、向きは達成されませんでした。つまり、カメラの対物レンズに直接面していない缶は認識されませんでした。

上記の4つの特定の問題を解決するために、OpenCV機能のみを使用して、特定のアルゴリズムを改善するのを手伝っていただけますか?

何かを学んでくれる人もいるといいのですが、結局、質問をする人だけが学ぶべきではないと思います。:)


45
この質問はdsp.stackexchange.comまたはstats.stackexchange.comでより適切であると言えるかもしれませんが、これらのサイトでも再度質問することを検討する必要があります。
エリー

49
ここで最初に行うことは、さまざまな障害ケースが発生している理由を分析することです。たとえば、ボトルが当たる場所、画像がぼやける場所などの例を分離し、統計分析を実行して、ハフ表現と検出したいものの違いを学習します。代替的なアプローチについて学ぶためにいくつかの素晴らしい場所があり、ここここに
エリー

7
@stackerは良い点です。速度を上げるには、方向性のあるグラデーションのヒストグラムなど、安価な計算機能を使用します。本当にナイーブな最初のアプローチは、いくつかのトレーニング画像で缶の長方形の束に手動でラベルを付け、これらに加えてランダムな負の例を使用してSVMまたは決定木分類器をトレーニングすることです。トレーニングには時間がかかりますが、新しい画像での実行ははるかに速くなります。適切な参照を含めるための空き時間ができたら、このメソッドを作成する予定です。
e12年

9
reCAPTCHAに似たアプローチはどうですか?;)
ジョージ・デュケット

39
なぜこれがdsp.stackexchange.comから移動されたのですか?そのサイトは、stackoverflow o_Oよりもはるかに適しているようです
BlueRaja-Danny Pflughoeft 2012

回答:


672

別のアプローチは、スケール不変の特徴変換(SIFT)または高速化された堅牢な特徴(SURF)を使用して特徴(キーポイント)を抽出することです。

OpenCV 2.3.1で実装されています。

Features2D + Homographyの機能を使用して、既知のオブジェクトを見つけるのに適したコード例を見つけることができます

どちらのアルゴリズムも、スケーリングと回転に対して不変です。それらは機能で動作するため、オクルージョンも処理できます(十分なキーポイントが表示されている限り)。

ここに画像の説明を入力してください

画像ソース:チュートリアルの例

SIFTの処理には数百ミリ秒かかります。SURFは少し高速ですが、リアルタイムアプリケーションには適していません。ORBは、回転不変性に関して弱いFASTを使用します。

オリジナルの論文


6
@stackerに同意します-SIFTは優れた選択肢です。スケールや回転操作に対して非常に堅牢です。これは、遠近法による変形に対して多少堅牢です(これは、スタッカーによって提案されているように改善できます:目的のオブジェクトの異なる遠近法ビューを持つテンプレートデータベース)。私の経験では、そのアキレス腱は強い照明の変化と非常に高価な計算になるでしょう。Javaの実装については知りません。私はOpenCV実装を認識しており、リアルタイムパフォーマンスに適したGPU c ++ / Windows(SiftGPU)実装を使用しています。

31
警告の注記:私がSIFT / SURFを好きで、彼らが私にしてきたことと同じくらい、彼らは特許に邪魔されています。これ、地理的な位置のAFAIKを含むいくつかの条件によっては、問題になる可能性あります。
Agos 2012

12
したがって、特許の問題がないOpenCVのORBまたはFREAKを試してください。ORBはSIFTよりもはるかに高速です。ORBそれは私の経験ではスケールと軽い変動で少し貧弱ですが、自分でテストしてください。
Rui Marques

66
どのようにこれを回答として受け入れることができますか?機能記述子のどれも、ボトルを缶から区別できません。それらはすべて、不変のローカルパターン記述子を表示するだけです。SIFT、SURF、ORB、FREAKなどが機能のマッチングで役立つことに同意しますが、オクルージョン、ボトルと缶など、質問の他の部分についてはどうでしょうか。おそらく最初の結果はこの答えだけになるでしょう。
G453

11
@ G453あなたは絶対的に正しいです!おそらく彼はSHIFTのパフォーマンスに魅了され、特徴の抽出とマッチングが問題では
なかった

383

物事をスピードアップするために、私はあなたが任意の画像/オブジェクトではなく、具体的にはコカコーラのロゴが付いているものを見つけるように求められるという事実を利用します。このロゴは非常に特徴的であり、周波数領域、特にRGBの赤チャネルで特徴的なスケール不変のシグネチャを持つ必要があるため、これは重要です。つまり、水平走査線(水平に配置されたロゴでトレーニング)が遭遇する赤から白から赤への交互のパターンは、ロゴの中心軸を通過するときに特有の「リズム」を持ちます。そのリズムは、異なるスケールと方向で「スピードアップ」または「スローダウン」しますが、比例して同等のままです。このようなスキャンラインを数十ダース(ロゴを通して水平および垂直の両方で、さらに斜めにいくつか)識別/定義できます。スターバーストパターンで。これらを「署名スキャンライン」と呼びます。

署名スキャンライン

ターゲットイメージでこのシグネチャを検索することは、イメージを水平ストリップでスキャンするという単純な問題です。赤のチャネル(赤の領域から白の領域に移動していることを示す)で高周波を探し、見つかったら、トレーニングセッションで特定された周波数リズムの1つが続いているかどうかを確認します。一致が見つかると、スキャンラインの向きとロゴ内の位置(トレーニング中にそれらを追跡する場合)がすぐにわかるので、そこからロゴの境界を特定するのは簡単です。

これが線形的に効率的なアルゴリズムではなかったとしたら、私は驚きます。それは明らかにあなたの缶瓶の差別に対処しませんが、少なくともあなたはあなたのロゴを持っています。

(更新:ボトルの認識のために私は(コークスのロゴに隣接した茶色の液体)になります-であり、内部のボトルまたは、空のボトルの場合には、私が探します。キャップは常に持っています基本的な形、サイズ、ロゴからの距離は同じで、通常はすべて白または赤になります。ロゴに対して、キャップを配置する必要がある無地の楕円形を検索してください。もちろん、絶対確実ではありませんが、ここでの目標は簡単なものをすばやく見つけてください。)

(画像処理の日から数年が経っていたので、この提案を高レベルで概念的なものにしました。人間の目がどのように機能するか、または少なくとも私の脳がどのように機能するかは、おおよそのことだと思います。)


24
それは素晴らしい提案です。私は特に、このアルゴリズムがおそらく多くの偽陰性を持っているとしても、かなり高速であるべきであるという事実を気に入っています。私の隠された目標の1つは、この検出をリアルタイムでロボット工学に使用することです。
Charles Menguy、

42
はい、多くの場合、近似アルゴリズムがほとんどのリアルタイムの現実世界のモデリングタスクに不可欠であることは(精度が特徴の分野では)忘れられます。(私はこの概念に基づいて論文を作成しました。)限られた地域で時間のかかるアルゴリズムを節約します(誤検知を排除します)。そして覚えておいてください:ロボット工学では、通常、単一の画像に限定されません。移動ロボットを想定すると、高速なアルゴリズムは、高度なアルゴリズムが費やす時間よりも短い時間でさまざまな角度から数十枚の画像を検索できるため、偽陰性を大幅に削減できます。
kmote 2012

29
コカコーラのロゴを非常に高速に検出するため、バーコードスキャナーに相当するものを使用するアイデアが気に入っています。+1!
Li-aung Yip、2012

8
この場合に署名を探す際の問題は、缶を反対側に向ける、つまり署名を隠すと、アルゴリズムが缶の検出に失敗することです。
karlphillip

34
@karlphillip:署名、つまりロゴを非表示にすると、ロゴの検索に基づく方法はすべて失敗します。
Li-aung Yip 2012

162

面白い問題:ボトルの画像をちらっと見たとき、それも缶だと思いました。しかし、人間として、私が違いを伝えるためにやったのは、それがボトルでもあることに気付いたということです...

だから、缶とボトルを区別するために、最初にボトルをスキャンするだけではどうですか?見つけた場合は、缶を探す前にラベルを覆ってください。

すでに缶を作っているなら、実装するのはそれほど難しくありません。実際の欠点は、処理時間が2倍になることです。(しかし、実際のアプリケーションを先に考えると、とにかくボトルを作りたくなるでしょう;-)


5
うん、私もそれについて考えましたが、それをする時間があまりありませんでした。ボトルは本体が目盛り付きの缶のように見えるので、どのように認識しますか 私も赤いプラグを探して、それがボトル入りの中心に揃っているかどうかを考えていましたが、それはあまり堅牢ではないようです。
Charles Menguy

42
「コカ・コーラ」と並行して赤いキャップ(またはリング)がある場合、それはおそらくボトルです。
Lukasz Madon 2012

@linker缶のアルゴリズムをどのようにトレーニングしましたか?缶の例はありましたか?ボトルの例を使ったトレーニングはどうですか?
siamii

1
このアルゴリズムの長所は、トレーニングするテンプレートが1つだけ必要であり、他の潜在的な缶と一致するようにすべての変換を適用することです。このテンプレートの2値化された輪郭ベースのバージョンを使用してトレーニングを行っていたため、缶とボトルの唯一の違いはプラグですが、重心が端のどこかにあるため、誤検知が増えると思いますまたはボトルの外。試してみる価値はあると思います。しかし、それは私の処理時間を2倍にし、私は泣くつもりです;)
Charles Menguy

7
基本的にこれは合理的な方向です。私は少し違う言い方をします。最初にすべての候補を見つけ、次に各候補についてそれがボトル、缶、または何か他のものであるかどうかを決定します。
MSalters 2012

131

人間でも、2番目の画像でボトルと缶を区別することは困難ではありませんか(ボトルの透明領域が非表示の場合)。

非常に小さな領域を除いて、ほとんど同じです(つまり、缶の上部の幅は少し狭く、ボトルのラッパーは全体で同じ幅ですが、小さな変更ですよね?)

最初に頭に浮かんだのは、ボトルの赤い上部を確認することでした。しかし、ボトルの上部がない場合、またはボトルが部分的に隠されている場合(上記のとおり)は、依然として問題です。

次に考えたのは、ボトルの透明度です。OpenCVには、画像内の透明なオブジェクトを見つける作業があります。以下のリンクを確認してください。

特にこれを見て、ガラスをどの程度正確に検出するかを確認してください。

それらの実装結果を見る:

ここに画像の説明を入力してください

彼らはそれが紙の実装であると言います 、K。McHenryとJ. PonceによるCVPR 2006「A Geodesic Active Contour Framework for Finding Glass」ます。

あなたの場合は少し役立つかもしれませんが、 、ボトルがいっぱいになると問題が再び発生します。

したがって、ここでは、最初にボトルの透明なボディを検索するか、または明らかにボトルである2つの透明なオブジェクトに横方向に接続されている赤い領域を検索できます。(理想的には以下のような画像になります。)

ここに画像の説明を入力してください

これで、黄色の領域、つまりボトルのラベルを削除し、アルゴリズムを実行して缶を見つけることができます。

とにかく、このソリューションには他のソリューションと同様にさまざまな問題があります。

  1. ボトルが空の場合にのみ機能します。その場合、2つの黒い色の間の赤い領域を検索する必要があります(コカコーラ液が黒い場合)。
  2. 透明部分が覆われている場合の別の問題。

しかし、とにかく、写真に上記の問題のいずれもない場合、これはより良い方法のようです。


+1私はこれについて考え、このアプローチを実装するために私の方法でした。ただし、@ linkerは彼の一連の画像を共有する必要があります。そうすることで、より知識に基づいた推測を行うことができます。
karlphillip

ええ..私はあまりにも多くの画像があった場合それが良かったと思っています。
Abid Rahman K

ボトル/缶のラベルのみがあり、ボトルキャップや透明度、または缶の上部/下部のその他の識別要素がない場合を考慮-ボトルの幅は缶の幅とは異なります。
Ken

ボトルのロゴの前に缶が置かれているとどうなりますか?
AlgoRythm

51

私はこの問題に対するダレン・クックスタッカーの答えが本当に好きです。私はそれらについてのコメントに自分の考えを投げ込んでいる最中でしたが、私のアプローチはここを離れないには答えの形をしていると思います。

要約すると、コカコーラのロゴが空間の特定の場所に存在することを決定するアルゴリズムを特定しました。ここでは、任意の方向と任意のスケーリング係数について、コカ・コーラを他のオブジェクトと区別するのに適したヒューリスティックを決定しようとしています。これには、ボトル看板広告コカ・コーラ道具が含まれます。すべてこのアイコンのロゴに関連付けられています。問題のステートメントでこれらの追加のケースの多くを呼び出さなかったが、私はそれらがアルゴリズムの成功に不可欠であると感じている。

ここでの秘密は、にどのような視覚的特徴含まれているか、または否定的な空間を通じて、缶には存在しない他のコーラ製品にどのような特徴が存在するかを決定することです。そのために、現在のトップアンサーは、「ボトル」がボトルキャップ、液体、またはその他の同様の視覚的ヒューリスティックの存在によって識別されない場合にのみ、「缶」を選択するための基本的なアプローチを示しています。

問題はこれが故障することです。たとえば、ボトルが空で、キャップがないため、誤検知が発生する可能性があります。または、追加の機能が損なわれた部分的なボトルであり、再び誤検出につながる可能性があります。言うまでもなく、これはエレガントではなく、私たちの目的にも効果的ではありません。

このため、缶の最も適切な選択基準は次のようです。

  • 質問スケッチしたオブジェクトのシルエットの形状は正しいですか?もしそうなら、+ 1。
  • 自然光または人工光の存在を想定している場合、これがアルミニウム製かどうかを示すボトルのクロムの輪郭を検出しますか?もしそうなら、+ 1。
  • 光源と比較して、オブジェクトの鏡面反射特性が正しいと判断しますか(光源検出に関するビデオリンクの例)。もしそうなら、+ 1。
  • 缶であると特定できる、オブジェクトに関する他のプロパティを特定できますか?ロゴのトポロジー的な画像のゆがみ、オブジェクトの向き、オブジェクトの並置(たとえば、平面上の)などテーブルのように、または他の缶のコンテキストで)、プルタブの存在?もしそうなら、それぞれ、+ 1。

分類は次のようになります。

  • 一致する候補ごとに、コカコーラのロゴの存在が検出された場合は、灰色の境界線を描画します。
  • +2を超える一致ごとに、赤い境界線を描画します。

これは、検出されたものをユーザーに視覚的に強調し、破損した缶として正確に検出される可能性のある弱い陽性を強調します。

各プロパティの検出は、時間とスペースの複雑さが非常に異なるため、アプローチごとにhttp://dsp.stackexchange.comのクイックパスは、目的に最も適した最も効率的なアルゴリズムを決定するのに合理的です。ここでの私の意図は、純粋にそして単純に、候補検出スペースのごく一部を無効にすることによって何かが缶であるかどうか検出することを強調することですこの問題に対する最も堅牢または効果的な解決策ではなく、理想的には適切なアクションを実行する必要それに応じて。

そして、ハッカーニュースの投稿おめでとうございます!全体として、これは受け取った宣伝に値するかなり素晴らしい質問です。:)


2
それは少なくとも試す価値のある興味深いアプローチです。私はこの問題についてのあなたの推論が本当に好きです
Charles Menguy

これは私が考えていたものです。特定の種類の誤検知を除外しないでください。コークスができるもののより多くの機能を支配する。しかし、私は不思議に思っています:押し潰された缶についてあなたは何をしますか?つまり、あなたがコーラ缶を踏んでも、それはまだコーラ缶です。しかし、もう同じ形にはなりません。それとも問題はAI完全ですか?
Ian

41

形を見る

缶/瓶の赤い部分の形を見てみましょう。缶のラベルがまっすぐであるのに対して、缶が最上部でわずかに先細になっていることに注目してください。赤い部分の長さ全体で赤い部分の幅を比較することにより、これら2つを区別できます。

ハイライトを見る

ボトルと缶を区別する1つの方法は材料です。ボトルはプラスチック製で、缶はアルミニウム製です。十分に明るい状況では、鏡面反射性を見ることは、ボトルのラベルと缶のラベルを区別する1つの方法です。

私が知る限り、それは人間が2つのタイプのラベルの違いを言う方法です。照明条件が悪い場合、いずれにせよ2つを区別するのにある程度の不確実性があるに違いありません。その場合、透明/半透明のボトル自体の存在を検出できる必要があります。


アイデアは気に入っていますが、本当に良い照明条件が必要なようです。たとえば、缶とボトルの両方があるサンプル画像では、これを区別するのは少し難しいようです。
Charles Menguy 2012

あなたの例では、プラスチックラベルの鏡面反射性が、缶の非常に明るいスポットよりもはるかに拡散していることに注目してください。それはあなたが言うことができる方法です。
tskuzzy 2012

この場合、アルゴリズムで鏡面反射性をキャプチャするためにどのような色空間表現を使用しますか?これはRGBまたはHSVで取得するのが非常に難しいようです
Charles Menguy

3
光源が缶の後ろにあった場合はどうなりますか?見どころは分からないと思います。
Rui Marques

37

Zdenek KalalのPredatorトラッカーをご覧ください。ある程度のトレーニングが必要ですが、追跡されたオブジェクトがさまざまな方向とスケールでどのように見えるかをリアルタイムで学習し、リアルタイムで行うことができます。

ソースコードは彼のサイトで入手できます。これはMATLABにありますが、おそらくコミュニティメンバーによってすでにJava実装されています。C#でTLDのトラッカー部分を正常に再実装しました。私の記憶が正しければ、TLDはキーポイント検出器としてFernsを使用しています。トラッカーによって失われたオブジェクトを再取得するために、代わりにSURFまたはSIFTのいずれかを使用します(すでに@stackerによって提案されています)。トラッカーのフィードバックにより、時間の経過とともにオブジェクトを非常に高い精度で再取得できる動的なsift / surfテンプレートの動的リストを簡単に作成できます。

トラッカーのC#実装に興味がある場合は、遠慮なく質問してください。


興味深く見えるリンクをありがとう。トレーニングに関して、妥当な結果を得るために妥当なトレーニングセットのサイズはどれくらいですか?あなたがc#でさえ実装をしているなら、それもとても役に立ちます!
Charles Menguy 2012

TLDの調査中に、C#の実装を探している別のユーザーが見つかりました--- Githubで作業を行わない理由はありますか? stackoverflow.com/questions/29436719/...
spillner

2
NB Years、later、link is now dead
J Evans

33

制約のないカメラだけに限定されていない場合は、Xbox Kinectなどの距離センサーを使用するように移動できます。これにより、画像の深度と色に基づいて一致するセグメンテーションを実行できます。これにより、画像内のオブジェクトをより速く分離できます。次に、ICPマッチングまたは類似の手法を使用して、缶の外形や色だけでなく、缶の形状を一致させることもできます。円筒形であることを前提として、以前にターゲットの3Dスキャンを行っている場合、これはあらゆる方向の有効なオプションになる可能性があります。これらの手法は、特に速度の問題を解決するような特定の目的で使用する場合、特に非常に高速です。

また、必ずしも正確さや速度ではなく、楽しみのために、色相セグメント化された画像に訓練されたニューラルネットワークを使用して缶の形状を特定することもできます。これらは非常に高速であり、多くの場合、最大80/90%の精度があります。各画像で缶を手動で識別する必要があるため、トレーニングは少し長いプロセスになります。


3
実際、私は投稿でそれを説明しませんでしたが、この割り当てのために私はおよそ30枚の画像のセットを与えられ、説明されているようにさまざまな状況でそれらすべてに一致するアルゴリズムを実行しなければなりませんでした。もちろん、最終的にアルゴリズムをテストするためにいくつかの画像が差し出されました。しかし、私はKinectセンサーのアイデアが好きで、このトピックについてもっと読みたいです!
Charles Menguy

満足のいく結果を得るために、ニューラルネットワークを使用したトレーニングセットのサイズはおおよそどのくらいですか?この方法の良い点は、ほぼすべてに一致するテンプレートが1つだけ必要なことです。
Charles Menguy

2
画像のセットが事前定義され、制限されている場合、ハードコアの完璧な結果がプログラムに表示されます;)
sne11ius

ええ、アルゴリズムを実行するデータセットでトレーニングすると、完璧な結果が確実に得られます:)しかし、たとえばこの割り当ての場合、プログラムは最後に、一連の保留された画像で教師によってテストされました。堅牢でトレーニングデータに適合しないようなことをしたいのですが。
Charles Menguy 2012

トレーニングセットの数はさまざまですが、いくつかの点に注意する必要があります。トレーニングしすぎないでください。おそらく、精度がどのようになっているかを示すテストセットが必要です。また、トレーニングセットの数は、使用するレイヤーの数によって異なります。
ファンタスティックMr Fox

24

私は赤い長方形を検出します:RGB-> HSV、フィルター赤->バイナリ画像、閉じる(拡張してから侵食、imcloseMATLAB で知られています)

次に、長方形を最大から最小まで調べます。既知の位置/スケールに小さい長方形がある長方形は両方とも削除できます(ボトルの比率が一定であると仮定すると、小さい長方形はボトルキャップになります)。

これにより、赤い四角形が残ります。その場合、ロゴを検出して、赤い四角形であるかコークス缶であるかを確認する必要があります。OCRに似ていますが、既知のロゴがありますか?


2
これが移動された短い時間にDSPで議論されていたように、一部のボトルにはプラグがない可能性があります;)またはプラグが部分的に隠れている可能性があります。
Charles Menguy

22

これは非常にナイーブなアイデアかもしれません(またはまったく機能しないかもしれません)が、すべてのコークス缶の寸法は固定されています。したがって、同じ画像に缶とボトルの両方が含まれている場合は、サイズの考慮事項によってそれらを区別することができます(ボトルは大きくなります)。深度が不足しているため(3Dマッピングから2Dマッピングへ)、ボトルが縮小して表示され、サイズに違いがない可能性があります。ステレオイメージングを使用して一部の深度情報を復元してから、元のサイズを復元できます。


3
実際にはありません:サイズや向きの制約はありません(または向きはありますが、実際には処理していません)。そのため、ボトルを背景に遠くに配置し、缶を前景に配置できます。ボトルより。
Charles Menguy

幅と高さの比率がボトルと缶でかなり似ていることも確認したので、これも実際にはオプションではありません。
Charles Menguy

ラベル比率(商標であること)は同じです。したがって、(大きい)ボトルが画像上で少し離れている場合、そのサイズは缶のサイズとまったく同じになります。
littleadv

3
もう少し説明します。缶がz = 0にあり、ボトルがz = -100にあるとします。ボトルが遠いので小さく見えます。しかし、ボトルがz = -100にあり、z = 0にできることがわかっている場合、両方がz = 0に変換された場合、缶/ボトルの予想サイズを計算できます。したがって、それらは同じ深さであり、したがって、サイズに基づいて決定を下すことができます。
Sharad

2
これは単なるコメントであり、回答ではありませんが、120票の上記の回答としてのコメントよりも回答に近いです。
Fattie

22

うーん、私は実際に私は何かに夢中になっていると思います(これはこれまでで最も興味深い質問のようなしたがって、許容できる答えが見つかったとしても、「完全な」答えを探し続けないのは残念です。) 。

ロゴを見つけたら、あなたの悩みは半分終わった。次に、ロゴの周りの違いを理解する必要があります。さらに、できるだけ余分なことはしたくない。これは実はこの簡単な部分だと思います...

ロゴの周りには何がありますか?缶の場合、照明の効果にもかかわらず、基本的な色がまったく変化しない金属を見ることができます。ラベルの角度がわかっていれば、その真上に何があるかがわかるので、これらの違いを調べます。

ここでは、ロゴの上下は完全に暗く、色が一貫しています。その点で比較的簡単です。

ここでは、上下は明るいですが、色は一貫しています。それはすべて銀であり、実際にすべて銀の金属はかなり珍しく、一般的に銀色です。さらに、それは薄いスリザーで、すでに識別されている赤に十分に近いので、全長にわたって形状をトレースして、缶の金属リングと見なすことができるもののパーセンテージを計算できます。本当に、缶のどこかにそれが含まれていることを伝えるために、缶のほんの一部しか必要ではありませんが、それでも、何かが金属で覆われた空のボトルではないことを保証するバランスを見つける必要があります。

そして最後に、トリッキーなもの。しかし、それほど難しいことではありません。一度、赤いラッパーの真上(および真下)で確認できるものだけを見ていきます。透明です。つまり、背後にあるものは何でも表示されます。その背後にあるものは、缶の銀の円形の金属ほど色の一貫性がない可能性が高いので、それは良いことです。その背後にはさまざまなものがあり、空の(または透明な液体で満たされた)ボトルであるか、一貫した色であることがわかります。これは、液体で満たされたか、ボトルが単にボトルの前にあることを意味しますソリッドカラー。私たちは上と下に最も近いものを使って作業しており、適切な色が適切な場所にある可能性は比較的わずかです。缶の重要な視覚的要素がないため、それがボトルであることはわかっています。

(最後の1つは、空の大きなコカコーラボトルで私が見つけた最高のものでした-興味深いことに、キャップとリングは黄色で、キャップの赤みはおそらく信頼されるべきではないことを示しています)

プラスチックを抽象化した後でも、同じような色合いの銀がボトルの後ろにある、またはボトルが同じ色の銀色の液体で満たされているというまれな状況では、大まかに推定できるものに頼ることができます銀の形-私が述べたように、それは円形であり、缶の形に従います。しかし、画像処理に関する特定の知識がなくても、遅く聞こえます。さらに良いことに、側面を一度チェックして、これを推測してみませんかことに、ロゴそこに同じシルバー色がないことをか?ああ、でも、缶の後ろに同じ色のシルバーがあるとどうなりますか?次に、缶の上部と下部をもう一度見て、形状にもっと注意を払う必要があります。

これがどれほど完璧である必要があるかに応じて、非常に遅くなる可能性がありますが、私の基本的な概念は、最も簡単で最も近いものを最初にチェックすることだと思います。他の要素の形状を計算する作業に進む前に、すでに一致している形状(とにかくこれの最も重要な部分のようです)の周りの色の違いを確認します。それをリストするために、それは行きます:

  • 主な魅力を見つけます(赤いロゴの背景、および場合によってはオリエンテーションのためのロゴ自体。ただし、缶が裏返されている場合は、赤だけに集中する必要があります)。
  • 形状と方向を確認しますが、非常に特徴的な赤みによっても確認します
  • 形状の周りの色を確認します(すばやく簡単にできるため)
  • 最後に、必要に応じて、メインのアトラクションの周りのこれらの色の形状を確認して、正しい丸みを確認します。

あなたがこれを行うことができない場合、それはおそらく缶の上部と底部が覆われていることを意味し、人間が缶と瓶を確実に区別するために使用できた唯一の可能なことは、閉塞と反射です缶の、それは処理するのがはるかに難しい戦いになるでしょう。ただし、さらに進むには、他の回答で説明されている半透明のスキャン技術を使用して、缶/ボトルの角度を追跡し、よりボトルのような特性を確認することができます。

興味深い追加の悪夢には、ボトルの後ろの金属がラベルの上と下に偶然に表示されるような距離でボトルの後ろに座っている缶が含まれる場合があります。赤の全長に沿ってスキャンしている限り、失敗します。ラベル-偶然に缶を含むボトルを実際に検出していると見なすのではなく、実際に問題が発生する可能性のある場所で缶を検出していないため、より問題になります。その場合、ガラスは半分空になります!


免責事項として、私はこの質問以外の画像処理については経験も考えたこともありませんが、非常に興味深いので、かなり深く考えさせられ、他のすべての回答を読んだ後、これはおそらくそれを成し遂げるための最も簡単最も効率的な方法。個人的に、私はしていないだけでうれしい実際にこのプログラミングについて考える必要が!

編集する

MSペイントでの缶の描画不良 さらに、私がMSペイントで描いたこの図面を見てください。それは絶対にひどくて完全ではありませんが、形状と色だけに基づいて、それがどうなるかを推測できます。本質的に、これらはスキャンを煩わせるために必要な唯一のものです。その非常に特徴的な形と色の組み合わせを非常に近くで見たとき、他に何ができるでしょうか?ペイントしなかった部分、白い背景は、「一貫性のないもの」と見なされます。背景が透明な場合は、他のほとんどすべての画像を覆い隠すことができます。


10
赤の特定の色合いは主に主観的であり、照明の考慮事項とホワイトバランスの影響を強く受けます。あなたはそれらがどれだけ変化することができるかに驚くかもしれません。たとえば、この市松模様の錯覚を考えてみましょう。
タコ

2
@Octopusが投稿したリンクの更新:persci.mit.edu/gallery/checkershadow
Hat

知覚錯覚は、あなたのウェブカメラが見るもの、つまりあなたのコードが何を得るかに影響を与えません-人間の目がどのようにして脳をだますのか(?)
バーニー

17

私はOpenCVについては知りませんが、問題を論理的に見ると、探している画像、つまりコカコーラを変更することで、ボトルと缶を区別できると思います。缶の場合はコカコーラの上部に銀の裏地があり、ボトルの場合はそのような銀の裏地はないので、缶の上部まで組み込む必要があります。

しかし、明らかに、このアルゴリズムは缶の上部が隠されている場合には失敗しますが、そのような場合でも人間は2つを区別することができません(ボトル/缶のコカコーラ部分のみが表示されている場合)


1
私も同じ考えでしたが、写真の缶の角度によって、缶の上の銀の裏地が劇的に変化すると思います。直線でも円でもかまいません。たぶん彼は両方を参照として使用できますか?
Alexis Dufrenoy

15

私はチャレンジが好きで、問題を解決する答えを出したかったと思います。

  1. ロゴの特徴(キーポイント、SIFT、SURFなどの記述子)を抽出する
  2. ポイントをロゴのモデル画像と一致させます(ブルートフォースなどのマッチャーを使用)
  3. リジッドボディの座標を推定する(PnP問題-SolvePnP)
  4. 剛体に従ってキャップ位置を推定します
  5. 逆投影を行い、ボトルのキャップの画像ピクセル位置(ROI)を計算します(カメラの固有パラメーターがあると想定しています)。
  6. キャップの有無は方法で確認してください。もしあれば、これがボトルです

キャップの検出は別の問題です。複雑でも簡単でもかまいません。私があなただったら、簡単な決定のためにROIのカラーヒストグラムをチェックするだけです。

私が間違っている場合は、フィードバックをお願いします。ありがとう。


13

この質問への回答が数年遅れています。過去5年間でCNNによって最先端の技術が限界に追いやられたので、今はOpenCVを使用してこのタスクを実行しません!(私はあなたが質問でOpenCv機能を特に欲しかったことを知っています)Faster-RCNN、YOLO、SSDなどのオブジェクト検出アルゴリズムはOpenCV機能と比較してかなりのマージンでこの問題を解決すると思います。私がこの問題に取り組む場合(6年後!!)、間違いなくFaster-RCNNを使用します。


5
OPによると、高解像度の画像は30枚あり、これはおそらくConvNetのトレーニングに最適なシナリオではありません。それらが少なすぎるだけでなく(増強されても)、高解像度の部分はConvNetを破壊します。
Kostas Mouratidis

11

トピックから外れているかどうかに関係なく、私はあなたの質問が好きです:P

興味深いことに、私は、ロボット工学とコンピュータービジョンを取り上げた学位を取得しました。学期のための私たちのプロジェクトはあなたが説明するものと信じられないほど似ていました。

Xbox Kinectを使用して、さまざまな照明や環境条件でコーラの瓶や缶をあらゆる方向に検出するロボットを開発する必要がありました。私たちのソリューションは、ハフサークル変換と組み合わせてHueチャネルでバンドパスフィルターを使用することを含みました。環境を少し制限することができました(ロボットとKinectセンサーをどこにどのように配置するかを選択できました)。それ以外の場合は、SIFTまたはSURF変換を使用しました。

このトピックについての私のブログ投稿で、私たちのアプローチについて読むことができます:)


2
興味深いプロジェクトですが、非常に具体的な設定にのみ適用されます。
Rui Marques

10

オブジェクトの認識に使用される色記述子はたくさんあります。以下の論文では、それらの多くを比較しています。これらは、SIFTまたはSURFと組み合わせると特に強力です。SURFまたはSIFTだけでは、コカ・コーラ缶の画像ではあまり有用ではありません。関心のあるポイントが多く認識されないため、カラー情報が必要になるためです。プロジェクトでSURFを使用してBIC(ボーダー/インテリアピクセル分類)を使用していますが、オブジェクトを認識するのに非常に役立ちました。

Web画像検索のための色記述子:比較研究


10

深層学習

コーラ缶を含む少なくとも数百の画像を収集し、それらの周囲の境界ボックスにポジティブクラスとして注釈を付け、コーラボトルと他のコーラ製品にネガティブクラスとランダムオブジェクトのラベルを付けます。

非常に大きなデータセットを収集しない限り、小さなデータセットに対してディープラーニング機能を使用するトリックを実行してください。理想的には、サポートベクターマシン(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


9

経験から分類の精度を有機的に学習および改善するプログラムが必要です。

私はディープラーニングを提案します。ディープラーニングでは、これは些細な問題になります。

TensorflowでInception v3モデルを再トレーニングできます。

新しいカテゴリのInceptionの最終レイヤーを再トレーニングする方法

この場合、畳み込みニューラルネットワークをトレーニングして、コカコーラができるかどうかに応じてオブジェクトを分類します。


2
ホットドッグかどうか。
YellowPillow 2018

6

これらすべての優れたソリューションの代わりに、独自の分類子をトレーニングして、アプリケーションをエラーに対して堅牢にすることができます。たとえば、Haar Trainingを使用して、ターゲットのポジティブイメージとネガティブイメージを適切な数だけ提供できます。

缶のみを抽出すると便利で、透明なオブジェクトの検出と組み合わせることができます。


3

MVTecのHALCONと呼ばれるコンピュータービジョンパッケージがあります。デモあなたに良いアルゴリズムのアイデアを与えることができるが。デモモードで実行し、コード内の演算子を確認し、既存のOpenCV演算子からそれらを実装する方法を確認できる、問題に似た例がたくさんあります。

このパッケージを使用して、このような問題の複雑なアルゴリズムのプロトタイプをすばやく作成し、既存のOpenCV機能を使用してそれらを実装する方法を見つけました。特にあなたのケースでは、オペレーターfind_scaled_shape_modelに埋め込まれた機能をOpenCVに実装しようとすることができます。一部のオペレーターは、OpenCVで同様のことを行う方法を見つけるのに役立つアルゴリズムの実装に関する科学論文を指しています。お役に立てれば...


0

リアルタイムに関心がある場合は、前処理フィルターに追加して、ヘビーデューティなものでスキャンする対象を決定する必要があります。コカ・コーラである可能性が高いものをスキャンできる、高速で非常にリアルタイムな前処理フィルターは、次のようなものです。画像を検索して、最大のパッチを探します。sqrt(pow(red,2) + pow(blue,2) + pow(green,2))あなたのコカ・コーラ缶のそれからある特定の許容範囲である色の。非常に厳密な色の許容値から始めて、より緩やかな色の許容値にまで進みます。次に、ロボットが現在のフレームを処理するために割り当てられた時間を使い果たすと、現在検出されているボトルを目的に使用します。RGBカラーを微調整してsqrt(pow(red,2) + pow(blue,2) + pow(green,2))適切に調整する必要があることに注意してください。

また、これは本当に馬鹿げているように見え-oFastますが、Cコードをコンパイルするときにコンパイラの最適化を必ずオンにしましたか?


0

多分何年も遅れるかもしれませんが、それでも試すべき理論です。

ボトル/缶の全体の寸法に対する赤いロゴ領域の外接する長方形の比率は異なります。缶の場合は1:1である必要がありますが、ボトルの場合は異なります(キャップ​​付きまたはキャップなし)。これにより、2つを簡単に区別できるようになります。

更新:ロゴ領域の水平方向の曲率は、それぞれのサイズの違いにより、缶とボトルで異なります。これは、ロボットが缶/ボトルを拾う必要があり、それに応じてグリップを決定する場合に特に役立ちます。


-1

私が最初に探すのは色です-REDのように、画像で赤目検出を行う場合-検出する特定の色範囲があり、周囲の領域を考慮した場合のいくつかの特性と、他の目からの距離など画像に実際に表示されています。

1:最初の特性は色で、赤が非常に支配的です。コカ・コーラレッドを検出した後、いくつかの重要な項目があります1A:この赤い領域の大きさ(真の缶かどうかを判断するのに十分な量かどうか-10ピクセルではおそらく十分ではありません)、1B:含まれていますラベルの色-「コカ・コーラ」または波。1B1:ラベルである可能性が高いと見なすのに十分ですか。

アイテム1は一種のショートカットです-それが画像に存在しない場合の前処理-先に進みます。

その場合は、画像のそのセグメントを利用して、問題の領域を少しズームアウトし始めることができます。基本的に、周囲の領域/エッジを確認します...

2:上記の画像領域IDが1の場合-問題のアイテムの周囲のポイント[エッジ]を確認します。A:缶の上部または下部にあると思われるものはありますか-シルバー?B:ボトルは透明に見えるかもしれませんが、ガラステーブルもそうです-ガラステーブル/棚または透明な領域があります-もしそうなら、複数の可能性が出てきます。ボトルには赤いキャップが付いている場合がありますが、そうでない場合もありますが、ボトルの上部/ねじの形状、またはキャップが必要です。C:これが失敗した場合でも、AとBは缶-パーシャルになる可能性があります。パーシャルボトル/パーシャルは同じように見える可能性があるため、これはパーシャルの場合はより複雑です。小さめのボトルはサイズが似ているかもしれません。

3:上記の分析の後、レタリングと波のロゴを確認します。単語に含まれる一部の文字を検索できるため、すべてのテキストがないため、すべてのテキストを取得できない場合があるためです。できます。波はテキストの特定のポイントで(距離に関して)整列するので、その確率を検索して、波の距離xのそのポイントに存在する文字を知ることができます。


-9

これは私が取り組んだ古いプロジェクトです。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 &agrave; emporter","R&eacute;servation d&rsquo;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");
}

3
これは何をしますか?
user8408080
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.