在我的应用程序中,我希望用户能够选择ImageView
中包含的图像的某些内容。
要选择我为ImageView
类子类化的内容,使其实现OnTouchListener
,以便在其上绘制一个由用户决定边框的矩形。
以下是绘图结果的示例(了解它的工作原理,您可以将其视为在桌面上单击鼠标并拖动鼠标时):
现在我需要确定Bitmap
图像的哪个像素对应于所选部分。很容易确定属于矩形的ImageView
的哪些点,但我不知道如何获得对应的像素,因为ImageView
具有与原始像素不同的宽高比图像。
我遵循especially here,but 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
,则应选择此区域:
答案 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());
现在你有了你想要的特定像素。