- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
目标是将 NV12 图像转换为 BGR24 图像,更确切地说是图像补丁 (x:0, y:0, w:220, h:220)。
问题是转换后的补丁右侧的未定义像素列,如图所示:
问题是为什么会发生这种情况(即使补丁的坐标和尺寸具有偶数值)?(有趣的是对于奇数宽度值,该问题不存在)
补丁具有以下边界框:(x:0, y:0, w:220, h:220)。
该行为应该可以用任何图像重现。可以使用 ppm conversion page 完成转换.
以下代码从 bgr24 图像创建 nv12 图像,然后将 nv12 补丁转换回 bgr24 补丁。 如果一切正常,输出应该与源图像相同。
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
void readPPM(const char* filename, uint8_t** bgrData, int* stride, int* w, int* h)
{
FILE* fp = fopen(filename, "rb");
fscanf(fp, "%*s\n"); //skip format check
fscanf(fp, "%d %d\n", w, h);
fscanf(fp, "%*d\n"); //skip max value check
*stride = *w * 3;
*bgrData = av_malloc(*h * *stride);
for (int r = 0; r < *h; r++)
{
uint8_t* rowData = *bgrData + r * *stride;
for (int c = 0; c < *w; c++)
{
//rgb -> bgr
fread(&rowData[2], 1, 1, fp);
fread(&rowData[1], 1, 1, fp);
fread(&rowData[0], 1, 1, fp);
rowData += 3;
}
}
fclose(fp);
}
void writePPM(const char* filename, uint8_t* bgrData, int stride, int w, int h)
{
FILE* fp = fopen(filename, "wb");
fprintf(fp, "P6\n");
fprintf(fp, "%d %d\n", w, h);
fprintf(fp, "%d\n", 255);
for (int r = 0; r < h; r++)
{
uint8_t* rowData = bgrData + r * stride;
for (int c = 0; c < w; c++)
{
//bgr -> rgb
fwrite(&rowData[2], 1, 1, fp);
fwrite(&rowData[1], 1, 1, fp);
fwrite(&rowData[0], 1, 1, fp);
rowData += 3;
}
}
fclose(fp);
}
void bgrToNV12(uint8_t* srcData[4], int srcStride[4],
uint8_t* tgtData[4], int tgtStride[4],
int w, int h)
{
struct SwsContext* context = sws_getContext(w, h, AV_PIX_FMT_BGR24,
w, h, AV_PIX_FMT_NV12, SWS_POINT, NULL, NULL, NULL);
{
sws_scale(context,
srcData, srcStride, 0, h,
tgtData, tgtStride);
}
sws_freeContext(context);
}
void nv12ToBgr(uint8_t* srcData[4], int srcStride[4],
uint8_t* tgtData[4], int tgtStride[4],
int w, int h)
{
struct SwsContext* context = sws_getContext(w, h, AV_PIX_FMT_NV12,
w, h, AV_PIX_FMT_BGR24, SWS_POINT, NULL, NULL, NULL);
{
sws_scale(context,
srcData, srcStride, 0, h,
tgtData, tgtStride);
}
sws_freeContext(context);
}
int main()
{
//load BGR image
uint8_t* bgrData[4]; int bgrStride[4]; int bgrW, bgrH;
readPPM("sample.ppm", &bgrData[0], &bgrStride[0], &bgrW, &bgrH);
//create NV12 image from the BGR image
uint8_t* nv12Data[4]; int nv12Stride[4];
av_image_alloc(nv12Data, nv12Stride, bgrW, bgrH, AV_PIX_FMT_NV12, 16);
bgrToNV12(bgrData, bgrStride, nv12Data, nv12Stride, bgrW, bgrH);
//convert nv12 patch to bgr patch
nv12ToBgr(nv12Data, nv12Stride, bgrData, bgrStride, 220, 220); //invalid result (random column stripe)
//nv12ToBgr(nv12Data, nv12Stride, bgrData, bgrStride, 221, 220); //valid result
//save bgr image (should be exactly as original BGR image)
writePPM("sample-out.ppm", bgrData[0], bgrStride[0], bgrW, bgrH);
//cleanup
av_freep(bgrData);
av_freep(nv12Data);
return 0;
}
最佳答案
sws_scale 同时进行颜色转换和缩放。
大多数使用的算法都需要在目标像素的计算中包括相邻像素。当然,如果图像尺寸不是 x 的倍数,这可能会导致边缘出现问题。其中 x 取决于所使用的算法。
如果您将此处的图像尺寸设置为 8 的倍数(下一个 8 的倍数 = 224),则它可以正常工作。
nv12ToBgr(nv12Data, nv12Stride, bgrData, bgrStride, 224, 224);
演示
在左侧使用 220 x 220 的图像尺寸,在转换后的补丁的右边缘给出一个伪影。
如果选择 224 x 224,它不会产生伪影,请参见比较两种程序的屏幕截图中的右侧图像。
理论上要求的最小对齐
我们来看一下YVU420格式:
亮度值是为每个像素确定的。颜色信息分为 Cb 和 Cr,由 2x2 像素 block 计算得出。因此,最小图像大小为 2 x 2 图像 block ,共 6 个字节(即每字节 12 个像素 = 12 * 4 = 48 位 = 6 字节),请参见此处的图形:
因此,最低技术要求是图像的宽度和高度均匀。
您已经为缩放定义了 SWS_POINT 标志,即使用最近邻方法。因此理论上,对于每个输出像素,确定并使用最近的输入像素,这不会造成任何对齐限制。
性能
但是,算法实际实现的一个重要方面通常是性能。在这种情况下,例如可以一次处理几个相邻的像素。也不要忘记硬件加速操作的可能性。
替代方案
如果出于某种原因您需要坚持使用 220x220 格式,您也可以使用 SWS_BITEXACT 标志。
确实如此:
Enable bitexact output.
参见 https://ffmpeg.org/ffmpeg-scaler.html#scaler_005foptions
所以在 nv12ToBgr 中你会使用像这样的东西:
struct SwsContext* context = sws_getContext(w, h, AV_PIX_FMT_NV12,
w, h, AV_PIX_FMT_BGR24, SWS_POINT | SWS_BITEXACT, NULL, NULL, NULL);
这也不会产生任何工件。如果您必须转换很多帧,我会看一下性能。
关于c - Swscale - 图像补丁(NV12)颜色转换 - 无效边框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56409122/
现在使用 nv.d3 示例中的 stackedAreaChart(),当您将鼠标悬停在时间序列中的某个点上时,您会得到一个工具提示。 我垂直对齐了 3 个时间序列。如果鼠标悬停在其中任何一个点上,我希
我正在尝试使用一些非核心硬件计数器,例如:skx_unc_imc0-5::UNC_M_WPQ_INSERTS .它应该计算写入挂起队列的分配数量。该机有2颗Intel Xeon Gold 5218 C
我正在使用 NVD3.js 库来生成图形。我尝试在其中添加折线图并得到上述错误。如何解决? 我正在尝试这个 here 最佳答案 其实我发现,问题是文件夹结构。 angular-nvd3 网站自带的例子
Closed. This question needs debugging details。它当前不接受答案。 想改善这个问题吗?更新问题,以便将其作为on-topic用于堆栈溢出。 4年前关闭。 I
我遇到了一些奇怪的事情!我为此使用了源代码:http://nvd3.org/ghpages/stackedArea.html#source_code 我在开头添加了这两行: 但是当我运行它时,它说
我是 Ubuntu 和网络开发的新手。我已经使用 nvd3 在我的一个项目中构建了一些折线图。最近我需要自定义这些折线图,我通过在 nv.d3.js 文件中进行一些编辑来实现。现在我正在尝试缩小该文件
v()有什么区别和 nv() oracle Apex中的功能? 我遇到了 nv()函数,我唯一能让谷歌吐出来的是 nvl()功能。 apex_custom_auth.post_login(
我留下了使用前一位开发人员的 nv.d3.js 构建的数据可视化图表,我目前正在尝试编辑饼图以将饼图定位在顶部,将标签定位在底部。这是一个视觉示例的 fiddle 。 https://jsfiddle
在我开始防止它变成一英里长的只写公式之前,我需要一些关于如何改进我的概念的想法...... 我正在尝试做的,以图形方式,是这样的: 我有两行有 4 个必需单元格(直线)和 4 个可选单元格(虚线),我
我正在尝试使用此处正确区域中的 NC/NV 服务器在 Azure 上创建 Windows 10 Pro VM:https://azure.microsoft.com/en-au/regions/ser
我有以下命令行交互说明的问题: $ wget www.google.com -nv >> out.log 2014-10-28 21:41:43 URL:http://www.google.com/
当从客户端使用此库的 sendBinary 时,我在服务器中得到的全是 0 ;( 此页面要求我添加更多描述,但下面的代码简单明了,应该可以 self 解释...... 客户端代码: private W
是否有任何方法可以捕获第 1/3 层 RF 相关信息或从 Android、Qualcomm 设备获取 NV 项目? 我从androiddocumentation中找到了一些参数我也试过 Qualcom
我使用“ssh -X machine”连接到远程 Linux 计算机,然后运行图形应用程序,因此它的窗口使用 X Window 显示在我的本地 OS X Lion 计算机上。我收到错误 “Xlib:显
我使用 nvd3 有用的预打包图表制作了一个堆积折线图。 我的图表可以很好地完成大部分功能,但每当我单击特定系列时,都会出现错误“未捕获类型错误:无法读取未定义的属性“y””,并且图表不会调整大小以仅
我正在尝试在node.js项目中创建一个virtualenv来管理nodejs依赖项,例如grunt、bower等。 尝试使用nodeenv来实现这一点。 但它没有得到认可。我同时使用了 npm in
所以我有一些看起来像这样的 HTML: 用相应的CSS like, svg { /*display: block;*/
我的数据框包含大约 26k 行和 129 个变量。我已经确保所有变量都是数字并且没有任何 NA 值(使用 na.omit)。在我的数据框上使用函数 prcomp() 告诉我“x 中有无限值或缺失值”。
我正在使用 nv.models.lineWithFocusChart ,我在这里展示了一些每小时的测量值。所以 x 域是日期。 我需要的是在 X 轴上每小时显示一个刻度: 00:00 01:00 02
我尝试在 ClustOfVar 包中应用稳定性函数并收到如下错误消息: Error in La.svd(x, nu, nv) : error code 1 from Lapack routine 'd
我是一名优秀的程序员,十分优秀!