如何创建尺寸为屏幕中心正方形的位图?
How to create a bitmap whose dimension is the central square of the screen?
背景与目标
我正在构建一个实时对象检测应用程序。为此,我需要一个 bitmap
来发送给识别算法。我有一个 activity 全屏显示相机输出,但我试图仅在屏幕的中央方块 上操作识别 。所以我需要一个具有这些尺寸和位置的位图,对应于 phone 屏幕的中央正方形。
我试过的
@Override
public void onPreviewSizeChosen(final Size size, final int rotation) {
/* some code... */
// Width of the screen (larger than the height), for my phone it's 4032
previewWidth = size.getWidth();
// Height of the screen, for my phone it's 1980
previewHeight = size.getHeight();
sensorOrientation = rotation - getScreenOrientation();
// The bitmap which will be used to the recognition, dimension : full screen of the phone
rgbFrameBitmap = Bitmap.createBitmap(previewWidth, previewHeight, Config.ARGB_8888);
// squared bitmap 320x320, required size for the recognition algorithm
croppedBitmap = Bitmap.createBitmap(cropSize, cropSize, Config.ARGB_8888);
// bitmap to croppedBitmap transform Matrix
frameToCropTransform =
ImageUtils.getTransformationMatrix(
previewWidth, previewHeight,
cropSize, cropSize,
sensorOrientation, MAINTAIN_ASPECT);
cropToFrameTransform = new Matrix();
frameToCropTransform.invert(cropToFrameTransform);
trackingOverlay = (OverlayView) findViewById(R.id.tracking_overlay);
trackingOverlay.addCallback(
new DrawCallback() {
@Override
public void drawCallback(final Canvas canvas) {
tracker.draw(canvas, isDebug());
}
});
tracker.setFrameConfiguration(previewWidth, previewHeight, sensorOrientation);
}
@Override
protected void processImage() {
trackingOverlay.postInvalidate();
if (computingDetection) {
readyForNextImage();
return;
}
computingDetection = true;
// THE LINE I CAN'T FIGURE OUT
// I try to set width and height = previewHeight (1980 for my phone so a square)
// and to move it down by (previewWidth-previewHeight)/2 so it goes in the middle of the screen
rgbFrameBitmap.setPixels(getRgbBytes(), 0, previewWidth, 0, (previewWidth-previewHeight)/2, previewHeight, previewHeight);
readyForNextImage();
final Canvas canvas = new Canvas(croppedBitmap);
canvas.drawBitmap(rgbFrameBitmap, frameToCropTransform, null);
// Saved set to true, so I can check what the bitmap sent to the recognition algorithm looks like
if (SAVE_PREVIEW_BITMAP) {
ImageUtils.saveBitmap(croppedBitmap);
}
runInBackground(
new Runnable() {
@Override
public void run() {
// Here we send the bitmap to the recognition algorithm to perform real-time detection
final List<Classifier.Recognition> results = detector.recognizeImage(croppedBitmap);
/* some code ... */
}
如果我将(previewWidth-previewHeight)/2
替换为0
作为rgbFrameBitmap.setPixels()
函数的y
参数,我设法在顶部的正方形中进行实时识别屏幕,如我所愿,除非它不居中。但是一旦我将 y
参数设置为 (previewWidth-previewHeight)/2
,这就是我在尝试保存位图时遇到的错误:
W/ImageReader_JNI: Unable to acquire a buffer item, very likely client tried to acquire more than maxImages buffers
如何让位图在屏幕中间居中?
横屏
要获得屏幕的中央正方形区域,请比较屏幕的 height
和 width
(以像素为单位)。通常对于桌面系统 width
更大,我假设是这种情况。
求出width
-height
的差,除以二,称其为x
。
最后画一个从(x, 0)到(x+height, height)的矩形。
更一般
正方形的边长将为 length = min(width,height)
广场的坐标将是
x = (width-length)/2
y = (height-length)/2
最后画一个从(x, y)到(x+length, y+length)的矩形。
自行解决
上面的代码有两点我误解了。
首先,我混淆了 rgbFrameBitmap.setPixels()
函数的 x
和 y
参数,但无论如何这只是在 space位图。要获得屏幕的中心,要改变的参数是offset
,像这样:
int x = (previewWidth-previewHeight)/2;
rgbFrameBitmap.setPixels(getRgbBytes(), x, previewWidth, 0, 0, previewHeight, previewHeight);
此外,当我们将 croppedBitmap
发送到识别算法时,由于矩阵 frameToCropTransform
,rgbFrameBitmap
被裁剪为 320x320,我不得不更新它:
frameToCropTransform =
ImageUtils.getTransformationMatrix(
previewWidth, previewHeight,
cropSize, cropSize,
sensorOrientation, MAINTAIN_ASPECT);
进入这个:
frameToCropTransform =
ImageUtils.getTransformationMatrix(
previewHeight, previewHeight,
cropSize, cropSize,
sensorOrientation, MAINTAIN_ASPECT);
因为 rgbFrameBitmap
现在是一个尺寸为 previewHeight
xpreviewHeight
的正方形
背景与目标
我正在构建一个实时对象检测应用程序。为此,我需要一个 bitmap
来发送给识别算法。我有一个 activity 全屏显示相机输出,但我试图仅在屏幕的中央方块 上操作识别 。所以我需要一个具有这些尺寸和位置的位图,对应于 phone 屏幕的中央正方形。
我试过的
@Override
public void onPreviewSizeChosen(final Size size, final int rotation) {
/* some code... */
// Width of the screen (larger than the height), for my phone it's 4032
previewWidth = size.getWidth();
// Height of the screen, for my phone it's 1980
previewHeight = size.getHeight();
sensorOrientation = rotation - getScreenOrientation();
// The bitmap which will be used to the recognition, dimension : full screen of the phone
rgbFrameBitmap = Bitmap.createBitmap(previewWidth, previewHeight, Config.ARGB_8888);
// squared bitmap 320x320, required size for the recognition algorithm
croppedBitmap = Bitmap.createBitmap(cropSize, cropSize, Config.ARGB_8888);
// bitmap to croppedBitmap transform Matrix
frameToCropTransform =
ImageUtils.getTransformationMatrix(
previewWidth, previewHeight,
cropSize, cropSize,
sensorOrientation, MAINTAIN_ASPECT);
cropToFrameTransform = new Matrix();
frameToCropTransform.invert(cropToFrameTransform);
trackingOverlay = (OverlayView) findViewById(R.id.tracking_overlay);
trackingOverlay.addCallback(
new DrawCallback() {
@Override
public void drawCallback(final Canvas canvas) {
tracker.draw(canvas, isDebug());
}
});
tracker.setFrameConfiguration(previewWidth, previewHeight, sensorOrientation);
}
@Override
protected void processImage() {
trackingOverlay.postInvalidate();
if (computingDetection) {
readyForNextImage();
return;
}
computingDetection = true;
// THE LINE I CAN'T FIGURE OUT
// I try to set width and height = previewHeight (1980 for my phone so a square)
// and to move it down by (previewWidth-previewHeight)/2 so it goes in the middle of the screen
rgbFrameBitmap.setPixels(getRgbBytes(), 0, previewWidth, 0, (previewWidth-previewHeight)/2, previewHeight, previewHeight);
readyForNextImage();
final Canvas canvas = new Canvas(croppedBitmap);
canvas.drawBitmap(rgbFrameBitmap, frameToCropTransform, null);
// Saved set to true, so I can check what the bitmap sent to the recognition algorithm looks like
if (SAVE_PREVIEW_BITMAP) {
ImageUtils.saveBitmap(croppedBitmap);
}
runInBackground(
new Runnable() {
@Override
public void run() {
// Here we send the bitmap to the recognition algorithm to perform real-time detection
final List<Classifier.Recognition> results = detector.recognizeImage(croppedBitmap);
/* some code ... */
}
如果我将(previewWidth-previewHeight)/2
替换为0
作为rgbFrameBitmap.setPixels()
函数的y
参数,我设法在顶部的正方形中进行实时识别屏幕,如我所愿,除非它不居中。但是一旦我将 y
参数设置为 (previewWidth-previewHeight)/2
,这就是我在尝试保存位图时遇到的错误:
W/ImageReader_JNI: Unable to acquire a buffer item, very likely client tried to acquire more than maxImages buffers
如何让位图在屏幕中间居中?
横屏
要获得屏幕的中央正方形区域,请比较屏幕的 height
和 width
(以像素为单位)。通常对于桌面系统 width
更大,我假设是这种情况。
求出width
-height
的差,除以二,称其为x
。
最后画一个从(x, 0)到(x+height, height)的矩形。
更一般
正方形的边长将为 length = min(width,height)
广场的坐标将是
x = (width-length)/2
y = (height-length)/2
最后画一个从(x, y)到(x+length, y+length)的矩形。
自行解决
上面的代码有两点我误解了。
首先,我混淆了 rgbFrameBitmap.setPixels()
函数的 x
和 y
参数,但无论如何这只是在 space位图。要获得屏幕的中心,要改变的参数是offset
,像这样:
int x = (previewWidth-previewHeight)/2;
rgbFrameBitmap.setPixels(getRgbBytes(), x, previewWidth, 0, 0, previewHeight, previewHeight);
此外,当我们将 croppedBitmap
发送到识别算法时,由于矩阵 frameToCropTransform
,rgbFrameBitmap
被裁剪为 320x320,我不得不更新它:
frameToCropTransform =
ImageUtils.getTransformationMatrix(
previewWidth, previewHeight,
cropSize, cropSize,
sensorOrientation, MAINTAIN_ASPECT);
进入这个:
frameToCropTransform =
ImageUtils.getTransformationMatrix(
previewHeight, previewHeight,
cropSize, cropSize,
sensorOrientation, MAINTAIN_ASPECT);
因为 rgbFrameBitmap
现在是一个尺寸为 previewHeight
xpreviewHeight