ImageView坐标和位图像素之间的对应关系 - Android

时间:2012-07-04 20:14:08

标签: java android android-imageview android-image

在我的应用程序中,我希望用户能够选择ImageView中包含的图像的某些内容。

要选择我为ImageView类子类化的内容,使其实现OnTouchListener,以便在其上绘制一个由用户决定边框的矩形。

以下是绘图结果的示例(了解它的工作原理,您可以将其视为在桌面上单击鼠标并拖动鼠标时):

enter image description here

现在我需要确定Bitmap图像的哪个像素对应于所选部分。很容易确定属于矩形的ImageView的哪些点,但我不知道如何获得对应的像素,因为ImageView具有与原始像素不同的宽高比图像。

我遵循especially herebut also here所描述的方法,但我并不完全满意,因为在我看来,ImageView上的像素和点之间的对应关系是1对1而不是将原始图像上的所有对应像素提供给选定区域。

调用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的方式变换坐标。这种方法显然是   对我的任务无效,因为某个区域的ImageView区域为50分   屏幕上的大小不能对应于真实中相同像素数的区域   图像,但应考虑不同的宽高比。

例如,如果图片小于应用中显示的ImageView,则应选择此区域:

enter image description here

3 个答案:

答案 0 :(得分:14)

Matteo,

似乎这更像是一个问题,即你可以(主观地)容忍你发送到服务器的像素有多少错误。事实仍然是,对于任何宽高整数的宽高比,你必须决定“推”选择框的方向。

您链接的解决方案是非常好的解决方案。您必须问自己:如果我处理的图像距离屏幕上显示的选择框有一个像素,用户是否会注意到?我的猜测可能不是。我无法想象当用户在触摸屏上选择一个带有大胖手指的矩形时,用户将具有那种像素精度:D

由于是这种情况,我只想让在转换为整数时发生的floor() - 处理您最终传递给服务器的像素。

让我们看一个例子。

让我们将ImageView和Bitmap的宽度和高度定义为:

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

现在,我将此Bitmap放在我的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,然后大约是像素的四分之一。好吧,如果我们floor()这个值和相应的BitmapPixelY值为8.36,我们将向服务器发送像素(119, 8)进行处理。如果我们要ceil()这些值,我们将向服务器发送像素(120,9)进行处理。 这部分完全取决于您。

你(几乎)总是落在像素的某个小部分。无论您发送的是您登陆的像素,还是旁边的像素都是您的通话。我想说这会让你的用户完全不知道,所以重申一下,只要让转换为整数时发生的floor()处理就可以了。

希望有所帮助!

[编辑]

再次慢慢阅读问题时,我想我更能理解你的疑问/困惑。我将使用上面的例子来说明。

你说的是Bitmap中有176个像素,ImageView中有400个像素。因此,从一个到另一个的映射不是1:1,这将在确定要处理哪些像素时会产生问题。

但事实并非如此!当您将ImageView中矩形边界的坐标转换为位图中的坐标时,您只需提供像素范围来迭代位图中的 这不是ImageView中每个像素如何映射到位图中相应像素的描述。

我希望这能让我对你的困惑感到困惑。

答案 1 :(得分:2)

这可以通过非常简单的数学来解决,你的矩形有4个点p1,p2,p3,p4,坐标x,y,相对于ImageView。

您还知道原始图像的尺寸。

现在,如果p1.x为50,则在宽度为200像素的ImageView中,得到50/200 = 0.25的关系

如果您的原始图像宽度为100像素,则您的点p1.x将位于100 * 0.25 = 25像素

可以表达:

  

50 - &gt; 200

     

? - &GT; 100

并计算:

  

? = 100 * 50/200

对每个点x,y执行此操作,然后在原始图像中获得矩形的4个点。

现在,如果您使用这些计算的点进行迭代,您应该获得原始图像中矩形的像素。

答案 2 :(得分: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());

现在你有了你想要的特定像素。