FFMPEG 是否在缩放后应用模糊滤镜?
Does FFMPEG apply a blur filter after scaling?
所以我正在实现我自己的双线性缩放版本,并将结果与 FFMPEG 和 ImageMagick 进行比较。这些工具创建了我的图像的缩放版本,但结果似乎不是仅通过应用插值操作获得的,结果似乎在缩放后出现模糊以消除锯齿。
这就是我的意思。
这是原始图像(6x6 yuv422p):
如您所见,只有黑白两列。
在使用双线性过滤器进行缩放操作后,我得到了黑色和白色之间的灰色列,这是预期的。这是我的结果:
我的图片 (12x12 yuv422p):
现在问题是FFMPEG的结果。正如我接下来要展示的,FFMPEG 创建的图像只有黑白两列,其余只有灰色阴影,这对双线性过滤没有意义。
FFMPEG 图像(12x12 yuv422p):
谁能告诉我 FFMPEG 在这种情况下做了什么?
// Iterate through each line
for(int lin = 0; lin < dstHeight; lin++){
// Get line in original image
int linOrig = lin / scaleHeightRatio;
float linOrigRemainder = fmod(lin, scaleHeightRatio);
float linDist = linOrigRemainder / scaleHeightRatio;
// For border pixels
int linIndexA = linOrig;
int linIndexB = linOrig + 1;
if(linIndexB >= srcHeight)
linIndexB = linIndexA;
linIndexA *= srcWidth;
linIndexB *= srcWidth;
// Iterate through each column
for(int col = 0; col < dstWidth; col++){
// Get column in original image
int colOrig = col / scaleWidthRatio;
float colOrigRemainder = fmod(col, scaleWidthRatio);
float colDist = colOrigRemainder / scaleWidthRatio;
// If same position as an original pixel
if(linOrigRemainder == 0 && colOrigRemainder == 0){
// Original pixel to the result
dstSlice[0][lin * dstWidth + col] = srcSlice[0][linOrig * srcWidth + colOrig];
dstSlice[1][lin * dstWidth + col] = srcSlice[1][linOrig * srcWidth + colOrig];
dstSlice[2][lin * dstWidth + col] = srcSlice[2][linOrig * srcWidth + colOrig];
// Continue processing following pixels
continue;
}
// For border pixels
int colIndexA = colOrig;
int colIndexB = colOrig + 1;
if(colIndexB >= srcWidth)
colIndexB = colIndexA;
// Perform interpolation
}
}
所以,我找到了问题所在。
考虑到性能,我将原始图片中的每个像素复制到与后者的像素完全对齐的缩放图片。
之后,我只对未知像素或未对齐像素进行插值,这实际上不是双线性插值的工作方式,因为它会产生锯齿。
FFMPEG 和所有其他图像处理工具在原始像素周围创建了一个填充,因此在我的情况下,我应该将 8x8 图片缩放为 12x12 图片,这将导致原始像素和缩放后的像素不会对齐图片。由于未对齐缩放图片的像素始终是原始图像像素的插值,它是周围像素的加权平均值,这就是为什么看起来 FFMPEG 缩放的结果是模糊的(因为它是从根本上说是平均)。
所以我正在实现我自己的双线性缩放版本,并将结果与 FFMPEG 和 ImageMagick 进行比较。这些工具创建了我的图像的缩放版本,但结果似乎不是仅通过应用插值操作获得的,结果似乎在缩放后出现模糊以消除锯齿。 这就是我的意思。
这是原始图像(6x6 yuv422p):
如您所见,只有黑白两列。 在使用双线性过滤器进行缩放操作后,我得到了黑色和白色之间的灰色列,这是预期的。这是我的结果:
我的图片 (12x12 yuv422p):
现在问题是FFMPEG的结果。正如我接下来要展示的,FFMPEG 创建的图像只有黑白两列,其余只有灰色阴影,这对双线性过滤没有意义。
FFMPEG 图像(12x12 yuv422p):
谁能告诉我 FFMPEG 在这种情况下做了什么?
// Iterate through each line
for(int lin = 0; lin < dstHeight; lin++){
// Get line in original image
int linOrig = lin / scaleHeightRatio;
float linOrigRemainder = fmod(lin, scaleHeightRatio);
float linDist = linOrigRemainder / scaleHeightRatio;
// For border pixels
int linIndexA = linOrig;
int linIndexB = linOrig + 1;
if(linIndexB >= srcHeight)
linIndexB = linIndexA;
linIndexA *= srcWidth;
linIndexB *= srcWidth;
// Iterate through each column
for(int col = 0; col < dstWidth; col++){
// Get column in original image
int colOrig = col / scaleWidthRatio;
float colOrigRemainder = fmod(col, scaleWidthRatio);
float colDist = colOrigRemainder / scaleWidthRatio;
// If same position as an original pixel
if(linOrigRemainder == 0 && colOrigRemainder == 0){
// Original pixel to the result
dstSlice[0][lin * dstWidth + col] = srcSlice[0][linOrig * srcWidth + colOrig];
dstSlice[1][lin * dstWidth + col] = srcSlice[1][linOrig * srcWidth + colOrig];
dstSlice[2][lin * dstWidth + col] = srcSlice[2][linOrig * srcWidth + colOrig];
// Continue processing following pixels
continue;
}
// For border pixels
int colIndexA = colOrig;
int colIndexB = colOrig + 1;
if(colIndexB >= srcWidth)
colIndexB = colIndexA;
// Perform interpolation
}
}
所以,我找到了问题所在。 考虑到性能,我将原始图片中的每个像素复制到与后者的像素完全对齐的缩放图片。 之后,我只对未知像素或未对齐像素进行插值,这实际上不是双线性插值的工作方式,因为它会产生锯齿。
FFMPEG 和所有其他图像处理工具在原始像素周围创建了一个填充,因此在我的情况下,我应该将 8x8 图片缩放为 12x12 图片,这将导致原始像素和缩放后的像素不会对齐图片。由于未对齐缩放图片的像素始终是原始图像像素的插值,它是周围像素的加权平均值,这就是为什么看起来 FFMPEG 缩放的结果是模糊的(因为它是从根本上说是平均)。