使用 Renderscript 启动选项裁剪图像数据
Crop image data using Renderscript Launch Options
我有一个灰度图像数据输入的 byte[] 数组,尺寸为宽度 * 高度。现在,我想通过应用翻译 (dx, dy) 来裁剪图像并切断边界外区域,以便 dataOut 具有维度 (width-abs(dx))*(height-abs(dy )).
在 RenderScript 中,我会为输入和输出使用 2-d uchar-Allocation。为了有效地应用裁剪操作,它正在考虑将 LaunchOptions 与(例如)setX(dx,width) 和 setY(0, height-dy) 一起使用,并应用一个简单的内核,它只从原始尺寸。
然而,当使用启动选项时,out-Allocation 仍然具有原始大小 width*height,即裁剪部分将仅显示为零 - 但是,我实际上希望将它们删除,即 out-分配是降维的。
问:在RS中是否有解决方案可以更优雅地执行此裁剪工作?感谢您的反馈。
更新:我想,我找到了解决方案。它是通过从一开始就将 out-Allocation 定义为缩减维度的全局脚本,传递 dx 和 dy 以及全局变量,然后应用 rsSetElementAt_uchar 来设置 out-Allocation 的值。稍后再更新。
所以,这是我的快速 rs-crop 工具,用 5 毫秒裁剪 500k 像素的图像。它使用 LaunchOptions 和缩小的尺寸来裁剪输出。如果您需要裁剪位图,只需分别使用元素类型 U8_4 和分配 uchar_4 而不是 U8 和 uchar。
crop.rs 文件:
#pragma version(1)
#pragma rs java_package_name(com.xxx.yyy)
#pragma rs_fp_relaxed
int32_t width;
int32_t height;
rs_allocation croppedImg;
uint xStart, yStart;
void __attribute__((kernel)) doCrop(uchar in,uint32_t x, uint32_t y) {
rsSetElementAt_uchar(croppedImg,in, x-xStart, y-yStart);
}
Java部分:
// data1 is the byte[] array with (grayvalue) data of size
// width*height you want to crop.
// define crop shift (dx, dy) here
int dx=0; // (-width < dx < width);
int dy=250; // (- height < dy < height);
int xStart=0, xEnd=0;
int yStart=0, yEnd=0;
// x direction
if (dx<0) {
xStart= Math.abs(dx);
xEnd=width;
}
else {
xStart = 0;
xEnd = width - Math.abs(dx);
}
// same for y direction
if (dy<0) {
yStart= Math.abs(dy);
yEnd=height;
}
else {
yStart = 0;
yEnd = height - Math.abs(dy);
}
// initiate rs and crop script
RenderScript rs = RenderScript.create(this);
ScriptC_crop mcropScr=new ScriptC_crop (rs);
// define allocations. Note the reduced size of cropAlloc
Type.Builder typeUCHAR = new Type.Builder(rs, Element.U8(rs));
typeUCHAR.setX(width).setY(height);
inAlloc = Allocation.createTyped(rs, typeUCHAR.create());
inAlloc.copyFrom(data1);
Type.Builder TypeUCHARCropped = new Type.Builder(rs, Element.U8(rs));
TypeUCHARCropped.setX(xEnd-xStart).setY(yEnd-yStart);
Allocation cropAlloc = Allocation.createTyped(rs, TypeUCHARCropped.create());
mcropScr.set_croppedImg(cropAlloc);
mcropScr.set_xStart(xStart);
mcropScr.set_yStart(yStart);
Script.LaunchOptions lo = new Script.LaunchOptions();
lo.setX(xStart, xEnd);
lo.setY(yStart, yEnd);
mcropScr.forEach_doCrop(inAlloc, lo);
byte[] data1_cropped =new byte[(xEnd-xStart)*(yEnd-yStart)];
cropAlloc.copyTo(data1_cropped);
与其他答案类似的想法,但这符合 Google 的 API 内在函数的风格:
#pragma version(1)
#pragma rs java_package_name(com.sicariusnoctis.collaborativeintelligence)
#pragma rs_fp_relaxed
rs_allocation input;
uint32_t xStart, yStart;
uchar4 RS_KERNEL crop(uint32_t x, uint32_t y) {
return rsGetElementAt_uchar4(input, x + xStart, y + yStart);
}
要设置:
fun setup(
width: Int, height: Int,
new_width: Int, new_height: Int,
xStart: Int, yStart: Int
) {
val inputType = Type.createXY(rs, Element.RGBA_8888(rs), width, height)
val outputType = Type.createXY(rs, Element.RGBA_8888(rs), new_width, new_height)
inputAllocation = Allocation.createTyped(rs, inputType, Allocation.USAGE_SCRIPT)
outputAllocation = Allocation.createTyped(rs, outputType, Allocation.USAGE_SCRIPT)
crop = ScriptC_crop(rs)
crop._xStart = xStart.toLong()
crop._yStart = yStart.toLong()
crop._input = inputAllocation
}
并执行:
fun execute(inputArray: ByteArray): ByteArray {
inputAllocation.copyFrom(inputArray)
crop.forEach_crop(outputAllocation)
val outputArray = ByteArray(outputAllocation.bytesSize)
outputAllocation.copyTo(outputArray)
return outputArray
}
我有一个灰度图像数据输入的 byte[] 数组,尺寸为宽度 * 高度。现在,我想通过应用翻译 (dx, dy) 来裁剪图像并切断边界外区域,以便 dataOut 具有维度 (width-abs(dx))*(height-abs(dy )).
在 RenderScript 中,我会为输入和输出使用 2-d uchar-Allocation。为了有效地应用裁剪操作,它正在考虑将 LaunchOptions 与(例如)setX(dx,width) 和 setY(0, height-dy) 一起使用,并应用一个简单的内核,它只从原始尺寸。
然而,当使用启动选项时,out-Allocation 仍然具有原始大小 width*height,即裁剪部分将仅显示为零 - 但是,我实际上希望将它们删除,即 out-分配是降维的。
问:在RS中是否有解决方案可以更优雅地执行此裁剪工作?感谢您的反馈。
更新:我想,我找到了解决方案。它是通过从一开始就将 out-Allocation 定义为缩减维度的全局脚本,传递 dx 和 dy 以及全局变量,然后应用 rsSetElementAt_uchar 来设置 out-Allocation 的值。稍后再更新。
所以,这是我的快速 rs-crop 工具,用 5 毫秒裁剪 500k 像素的图像。它使用 LaunchOptions 和缩小的尺寸来裁剪输出。如果您需要裁剪位图,只需分别使用元素类型 U8_4 和分配 uchar_4 而不是 U8 和 uchar。
crop.rs 文件:
#pragma version(1)
#pragma rs java_package_name(com.xxx.yyy)
#pragma rs_fp_relaxed
int32_t width;
int32_t height;
rs_allocation croppedImg;
uint xStart, yStart;
void __attribute__((kernel)) doCrop(uchar in,uint32_t x, uint32_t y) {
rsSetElementAt_uchar(croppedImg,in, x-xStart, y-yStart);
}
Java部分:
// data1 is the byte[] array with (grayvalue) data of size
// width*height you want to crop.
// define crop shift (dx, dy) here
int dx=0; // (-width < dx < width);
int dy=250; // (- height < dy < height);
int xStart=0, xEnd=0;
int yStart=0, yEnd=0;
// x direction
if (dx<0) {
xStart= Math.abs(dx);
xEnd=width;
}
else {
xStart = 0;
xEnd = width - Math.abs(dx);
}
// same for y direction
if (dy<0) {
yStart= Math.abs(dy);
yEnd=height;
}
else {
yStart = 0;
yEnd = height - Math.abs(dy);
}
// initiate rs and crop script
RenderScript rs = RenderScript.create(this);
ScriptC_crop mcropScr=new ScriptC_crop (rs);
// define allocations. Note the reduced size of cropAlloc
Type.Builder typeUCHAR = new Type.Builder(rs, Element.U8(rs));
typeUCHAR.setX(width).setY(height);
inAlloc = Allocation.createTyped(rs, typeUCHAR.create());
inAlloc.copyFrom(data1);
Type.Builder TypeUCHARCropped = new Type.Builder(rs, Element.U8(rs));
TypeUCHARCropped.setX(xEnd-xStart).setY(yEnd-yStart);
Allocation cropAlloc = Allocation.createTyped(rs, TypeUCHARCropped.create());
mcropScr.set_croppedImg(cropAlloc);
mcropScr.set_xStart(xStart);
mcropScr.set_yStart(yStart);
Script.LaunchOptions lo = new Script.LaunchOptions();
lo.setX(xStart, xEnd);
lo.setY(yStart, yEnd);
mcropScr.forEach_doCrop(inAlloc, lo);
byte[] data1_cropped =new byte[(xEnd-xStart)*(yEnd-yStart)];
cropAlloc.copyTo(data1_cropped);
与其他答案类似的想法,但这符合 Google 的 API 内在函数的风格:
#pragma version(1)
#pragma rs java_package_name(com.sicariusnoctis.collaborativeintelligence)
#pragma rs_fp_relaxed
rs_allocation input;
uint32_t xStart, yStart;
uchar4 RS_KERNEL crop(uint32_t x, uint32_t y) {
return rsGetElementAt_uchar4(input, x + xStart, y + yStart);
}
要设置:
fun setup(
width: Int, height: Int,
new_width: Int, new_height: Int,
xStart: Int, yStart: Int
) {
val inputType = Type.createXY(rs, Element.RGBA_8888(rs), width, height)
val outputType = Type.createXY(rs, Element.RGBA_8888(rs), new_width, new_height)
inputAllocation = Allocation.createTyped(rs, inputType, Allocation.USAGE_SCRIPT)
outputAllocation = Allocation.createTyped(rs, outputType, Allocation.USAGE_SCRIPT)
crop = ScriptC_crop(rs)
crop._xStart = xStart.toLong()
crop._yStart = yStart.toLong()
crop._input = inputAllocation
}
并执行:
fun execute(inputArray: ByteArray): ByteArray {
inputAllocation.copyFrom(inputArray)
crop.forEach_crop(outputAllocation)
val outputArray = ByteArray(outputAllocation.bytesSize)
outputAllocation.copyTo(outputArray)
return outputArray
}