12

私のアプリケーションでは、ユーザーが内に含まれる画像のコンテンツを選択できるようにしたいと思いますImageView

コンテンツを選択するために、ImageViewクラスをサブクラス化して実装OnTouchListenerし、ユーザーが決定した境界線を持つ長方形をその上に描画します。

描画結果の例を次に示します(どのように機能するかを知るために、デスクトップ上でマウスをクリックしてマウスをドラッグしたときのように考えることができます)。

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

次に、画像のどのピクセルBitmapが選択した部分に対応するかを判断する必要があります。長方形に属する点がどれであるかを判断するのは簡単ですが、元の画像とはアスペクト比が異なるImageViewため、対応するピクセルを取得する方法がわかりません。ImageView

私は特にここで説明されているアプローチに従いましたが、ここでも完全には満足していません。私の意見では、ピクセルと上のポイントの間の対応は1対1でありImageView、元の画像のすべての対応するピクセルが選択されたものに与えられないためです。範囲。

hoveredRectその内側のポイントで長方形を呼び出すと、ImageView次のようになります。

class Point {
    float x, y;
    @Override
    public String toString() {
        return x + ", " + y;
    }
}

Vector<Point> pointsInRect = new Vector<Point>();

for( int x = hoveredRect.left; x <= hoveredRect.right; x++ ){
    for( int y = hoveredRect.top; y <= hoveredRect.bottom; y++ ){

        Point pointInRect = new Point();
        pointInRect.x = x;
        pointInRect.y = y;
        pointsInRect.add(pointInRect);
    }   
}

Vector<Pixels> pixelsInImage画像の対応するピクセルを含むを取得するにはどうすればよいBitmapですか?


追加された説明

私の問題の文脈をもう少しよく説明します:

選択した部分で画像処理を行う必要があり、長方形のすべてのピクセルが確実に処理されるようにしたいです。

画像処理はサーバー上で実行されますが、処理するピクセルを正確に知る必要があります。サーバーは実際のサイズの画像で動作します。Androidアプリは、ピクセル座標を含むベクトルを渡すことで、サーバーに処理するピクセルを指示するだけです。

そして、なぜ私は上記のリンクで提案された解決策が好きではないのですか?

与えられた答えは、1対1の方法で座標を変換します。画面上の特定のサイズのたとえば50ポイントの領域は、実際の画像の同じピクセル数の領域に対応できないため、このアプローチは明らかに私のタスクには有効ではありませんImageViewが、異なるアスペクト比を考慮する必要があります。

ImageView例として、これは、画像がアプリに表示されているものよりも小さい場合に選択する必要がある領域です。

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

4

3 に答える 3

15

マッテオ、

これは、サーバーに送信するピクセルで(主観的に)許容できるエラーの量の問題のようです。きちんとした整数にならないアスペクト比の場合、選択ボックスを「押す」方向を決定する必要があるという事実は変わりません。

リンクしたソリューションは完全に優れたソリューションです。あなたは自分自身に問いかける必要があります:私が処理する画像が画面に表示された選択ボックスから1ピクセル離れているかどうかユーザーは気付くでしょうか?私の推測ではおそらくそうではありません。タッチスクリーン上で大きな太い指で長方形を選択するときに、ユーザーがとにかくそのようなピクセル精度を持っているとは想像できません:D

これが事実であるfloor()ため、整数にキャストするときに発生する-ingに、サーバーに渡す最終的なピクセルを処理させるだけです。

例を見てみましょう。

ImageViewとビットマップの幅と高さを次のように定義しましょう。

ImageViewWidth = 400, ImageViewHeight = 150
BitmapWidth = 176, BitmapHeight = 65

次に、選択ボックスをそれらの間で変換するために使用するアスペクト比は次のようになります。

WidthRatio = BitmapWidth / ImageViewWidth = 175 / 400 = 0.44
HeightRatio = BitmapHeight / ImageViewHeight = 65 / 150 = 0.44

いくつかの素敵な醜い数字。ImageViewで使用しているピクセルは、次のようにビットマップのピクセルに対応します。

BitmapPixelX = ImageViewPixelX * WidthRatio
BitmapPixelY = ImageViewPixelY * HeightRatio

ここで、このビットマップをImageViewの画面に配置して、ユーザーが長方形を選択できるようにします。ユーザーは、ImageViewで左上と右下の座標を持つ長方形を選択します。

RectTopLeftX = 271, RectTopLeftY = 19
RectBottomRightX = 313, RectBottomRightY = 42

これらが対応するビットマップのピクセルを特定するにはどうすればよいですか?簡単。以前に決定した比率。とりあえず左上の座標だけを見てみましょう。

RectTopLeftX * WidthRatio = 271 * .44 = 119.24
RectTopLeftY * HeightRatio = 19 * .44 = 8.36

RectTopLeftXの場合、BitmapPixelX値が119であり、ピクセルの約1/4の位置にあります。floor()この値と対応するBitmapPixelY値が8.36の場合、処理のためにピクセルをサーバーに送信し(119, 8)ます。これらの値にceil()達した場合、処理のためにピクセル(120、9)をサーバーに送信します。これは完全にあなた次第の部分です。

あなたは(ほぼ)常にピクセルの一部に着地します。着地したピクセルを送信するか、その隣のピクセルを送信するかは、あなたの呼び出しです。これはユーザーにはまったく気付かれることはないでしょう。繰り返しになりますfloor()が、整数にキャストするときに発生する-ingで処理してください。

お役に立てば幸いです。

[編集]

もう一度ゆっくりと質問を読むと、あなたが何を求めているのか、何について混乱しているのかがよく理解できたと思います。上記の例を使用して説明します。

あなたは、ビットマップに176ピクセル、ImageViewに400ピクセルがあると言っています。したがって、一方から他方へのマッピングは1:1ではなく、これにより、処理のためにどのピクセルを引き出すかを判断するときに問題が発生します。

しかし、そうではありません!ImageViewの長方形の境界の座標をビットマップの座標に変換する場合、ビットマップで反復するピクセルの範囲を指定するだけですこれは、ImageViewの個々のピクセルがビットマップの対応するピクセルにどのようにマッピングされるかについての説明ではありません。

それがあなたの混乱についての私の混乱を解消することを願っています。

于 2012-07-24T20:23:47.067 に答える
2

これは非常に単純な数学で解くことができます。長方形には、ImageViewを基準にした座標x、yを持つ4つのポイントp1、p2、p3、p4があります。

また、元の画像のサイズもわかっています。

たとえば、p1.xが50の場合、幅が200ピクセルのImageViewでは、50/200=0.25の関係になります。

元の画像の幅が100ピクセルの場合、ポイントp1.xは100 * 0.25=25ピクセルになります。

表現できる:

50-> 200

?-> 100

そして計算された:

?= 100 * 50/200

これを各ポイント、各次元x、yに対して実行すると、元の画像の長方形の4つのポイントが取得されます。

これらの計算されたポイントを使用して反復すると、元の画像の長方形のピクセルを取得する必要があります。

于 2012-07-04T21:07:06.183 に答える
0

ここでは、画像ビュー内に何かを配置したと想定しています。onCreate内でこれを行います:

ImageView image=(ImageView) findViewById(R.id.imageView1);
TextView coordinates=(TextView) findViewById(R.id.textView1);
bitmap = ((BitmapDrawable)Map.getDrawable()).getBitmap();

そしてこれはonTouchの内部です:

coordinates.setText("Touch coordinates:"+String.valueOf(event.getX())+"x"+String.valueOf(event.getY()));
int pixel = bitmap.getPixel((int)event.getX(), (int)event.getY());

これで、必要な特定のピクセルができました。

于 2012-07-24T23:00:00.740 に答える