1

私は、ゲームからレンダリングされた画像を処理する PHP 画像処理ライブラリに取り組んでおり、PHP Web ホストで処理されています。画像を処理するには、赤の島 (色相が 0 または 360 の x 量内にある) を見つけて、その中のポイントを取得する必要があります (中心である必要はありませんが、できれば中心近くです)。そのような島々は、大小合わせて約 100 あります。それらは台形またはそれに近いものです。画像は PNG であり、アンチエイリアシングなしで圧縮されていないため、エッジはピクセル単位で鮮明ですが、一部の領域は他の領域よりも暗い場合があります。

現在、私が試したのはimagecolorat(、GD で使用し、変換後に HSV 値をテストしてから、赤以外のピクセルに到達するまでその周りのポイントを試行することですが、そのプロセスが完了するまでに時間がかかり、PHP のタイムアウトが発生したようです。大きな画像を処理している場合は、5 秒の制限まで。上記の島を検出し、必ずしも中心ではなく、近くでポイントを取得するより効率的な方法はありますか?

また、台形のサイズがわかっている場合は、特定の距離内に何も来ないと仮定し、時間を節約するためにその距離をスキップしてみました。

必ずしもコードは必要ありません。正しい方向へのポインターだけです。

私の現在のコード:

function RGBToHSL($RGB) {
    $r = 0xFF & ($RGB >> 0x10);
    $g = 0xFF & ($RGB >> 0x8);

//をちょきちょきと切る }

$image=imagecreatefrompng($filename);
$redislands=[];
for($xpos=0; $xpos<=imagesx($image); $xpos++){
    for($ypos=0; $ypos<=imagesy($image); $ypos++){
        if (RGBToHSL(imagecolorat(xpos, ypos)->saturation<=20||RGBToHSL(imagecolorat(xpos, ypos)->saturation>=350){
            $redislands[]=[xpos, ypos]
            }
        }
    }
4

1 に答える 1

0

私は実際にgdを使用したことがありませんが、簡単に見てみるとわかります

imagefilter()IMG_FILTER_EDGEDETECT旗付き。

その後、単一の単純なループですべてのオブジェクトを識別できるようになります(オブジェクトのサイズが最小の場合、ループにこのストライプサイズを使用させても、各オブジェクトに遭遇することが保証されます)。エッジカラーのあるピクセルを探すだけで、見つけたら、エッジカラーのある隣接ピクセルを再帰的に探索します。たとえば、オブジェクトの高さが7ピクセル以上であることが保証されている場合、エッジが強調表示された後、行0、7、14、21などのピクセルをループするだけで済みます。

コンポーネントの周囲のエッジを使用してコンポーネントを抽出すると、その形状、色、および中心をかなり簡単に識別できると思います。

エッジが確実に検出されない場合は、画像のしきい値処理を試す必要があるかもしれません(gdはこれを行うことができます)。

真剣に検討するもう1つのオプションは、これにphpを使用せず、代わりにphpのexec()関数を使用して外部プログラムを実行することです。これにより、あらゆる種類のライブラリ(opencvなど)やこのようなものを対象としたプログラムを使用できるようになります。また、cのようなコードを書くこともできます...ピクセルの色を表す数百万のintを保持するac配列をループする速度に驚かれることでしょう。しかし、これはあなたにとって実行可能な選択肢ではないと私は感じています。

あなたが調査するかもしれない他の何かは、ピクセルのphp配列(または文字列)へのアクセスを得ることです。関数呼び出しのオーバーヘッドは大きく、imagecolorat()のような関数を何百万回も呼び出すことは、のようなネイティブのphp配列アクセスと比較して合計されます$pixels[$i]。画像形式については何も知りませんが、ビットマップとして保存して文字列にロードし、文字列オフセットを使用することもできます。ビットマップに適切な配列のようなバイナリ表現があれば、それは飛ぶでしょう。

于 2012-12-29T17:33:21.977 に答える