UPD。尚未找到解决方案,并且在评论中,有人可能会说,一种水,它没有明确解决问题。他们在评论中写道,他们说,由于整数除法,我得到了这样的结果。如果我将除以 4,那么为什么我会得到一个带有覆盖像素的相似图像?有趣的是,在java我附加的链接的实现中 - 没有除以 4 并且结果正确显示。我还不明白为什么除以 4c++给我的图片比例是 1 比 1,而java没有它的比例是相同的。如果你没有在加号中写除以 4,那么我只能得到四分之一的图片,而且还有白线。
UPD2。找到解决方案。但是我只是想了解-为什么在加号中我们除以rowBytes4,而在我附加的链接中的那个例子中的java中-没有除法,只有+4。然而,结果是一样的。有什么问题,或者我在哪里错过了什么?
我需要将bgr-array 转换为rgb-array。我很想使用现有库中的实现,但它们对我的项目来说太慢了。
我有我自己的jni- 函数c++,它可以转换一个数组,或者更确切地说是Frame从FFmpegFrameGrabber,它将在转换为Bitmap. 我只从那里取这个包:
(ByteBuffer) frame.image[0]; // здесь кадр в bgr-формате
我知道 和 中有不同的转换器opencv,javacv但性能对我的项目非常重要,因为框架必须到达我的神经元。因此,转换为矩阵,然后通过Utils.matToBitmapor转换AndroidFrameConverter,延迟约为 50 ms,不适合我。虽然 native 方法matToBitmap非常快,但它不适合,因为转换javacv Mat到opencvMat需要 ~100ms,这很多。cvtColor不适合类似的问题,因为它需要一个矩阵作为输入。
c++我基于AndroidFrameConverter从方法编写了自己的转换器:
ByteBuffer bgr2rgba(ByteBuffer in, int width, int height, int stride, int rowBytes{...}
我只为 编写了一个转换器ARGB_8888,即每像素 4 个字节。现在我的代码需要大约 8-15 毫秒来转换。但我不明白我在哪里错过了每 2 行像素 yBitmap不显示的部分代码。由于我的专业不强,所以我整理了这段代码:
#include <jni.h>
#include <endian.h>
extern "C"
JNIEXPORT jbyteArray JNICALL Java_com_example_testcpp_MainActivity_frameToBitmap(JNIEnv *env, jobject thiz, jobject in,
jint width, jint height, jint imageStride,
jint rowBytes) {
auto* buf = (uint8_t*) env->GetDirectBufferAddress(in);
int* new_buff = new int [4*width*height];
int _width = width - 1;
int _height = height - 1;
for (int y = 0; y < height; y++) {
int ro = y * imageStride;
for (int x = 0; x < width; x++) {
int rgb;
if (x < _width || y < _height) {
rgb = *(int*)(buf + y * imageStride + 3 * x);
} else {
int b = buf[ro + 3 * x ] & 0xff;
int g = buf[ro + 3 * x + 1] & 0xff;
int r = buf[ro + 3 * x + 2] & 0xff;
rgb = (r << 16) | (g << 8) | b;
}
new_buff[y / 4 * rowBytes + x] = htobe32((rgb << 8) | 0xff);
}
}
jbyteArray jByteArray = env->NewByteArray((jsize)4*width*height);
env->SetByteArrayRegion(jByteArray, 0, 4*width*height, reinterpret_cast<const jbyte*>(new_buff));
delete[] new_buff;
return jByteArray;
}
我在哪里犯c++了代码错误?
java函数调用:
Frame frame = grabber.grabImage();
ByteBuffer in = (ByteBuffer)frame.image[0];
Bitmap bmp = Bitmap.createBitmap(frame.imageWidth, frame.imageHeight, Bitmap.Config.ARGB_8888);
byte [] data = frameToBitmap(in, frame.imageWidth, frame.imageHeight, frame.imageStride, bmp.getRowBytes());
bmp.copyPixelsFromBuffer(ByteBuffer.wrap(data).position(0));
也许有人知道如何快速转换javacv Mat为opencv Mat然后通过快速的本机方法进行转换,Utils.matToBitmap以免创建自己的jni-function?很高兴听到更多关于如何优化和加速此代码的信息。

在引用代码中,缓冲区中的地址(以字节为单位)是在写入 int 时计算的,这里有一个 int 数组,其中的索引少 4 倍。
使用整数除法时,如注释中所述,结果不是您所期望的,因为
0/4 = 1/4 = 2/4 = 3/4 = 0. 这就是整数除法在 C 和 Java 中的工作方式。在这种情况下,为了得到正确的结果,首先执行乘法然后除法就足够了: