这个DemosaicMalvar函数是用opencvsharp实现matlab的demosaic函数,但是目前转出来的跟matlab有一点差异,图像有明显的一格一格的马赛克图案,我的问题是怎么修改这个函数要和matlab的结果一模一样
public static Mat DemosaicMalvar(Mat raw, string bayerPattern = "RGGB")
{
if (raw.Channels() != 1)
throw new ArgumentException("Input must be single-channel image");
int height = raw.Rows;
int width = raw.Cols;
// 将原始图像转换为32位浮点数
Mat rawFloat = new Mat();
raw.ConvertTo(rawFloat, MatType.CV_32F);
// 扩展边界(使用反射边界,与MATLAB一致)
Mat extended = new Mat();
Cv2.CopyMakeBorder(rawFloat, extended, 2, 2, 2, 2, BorderTypes.Reflect);
// 创建输出图像(32位浮点,三通道)
Mat rgb = new Mat(height, width, MatType.CV_32FC3);
// Malvar算法卷积核 (5x5) - 修正系数
float[,] kernelG = {
{ 0, 0, -1, 0, 0 },
{ 0, 0, 2, 0, 0 },
{-1, 2, 4, 2, -1 },
{ 0, 0, 2, 0, 0 },
{ 0, 0, -1, 0, 0 }
};
float[,] kernelRAtB = {
{ 0, 0, -1.5f, 0, 0 },
{ 0, 2, 0, 2, 0 },
{-1.5f, 0, 6, 0, -1.5f },
{ 0, 2, 0, 2, 0 },
{ 0, 0, -1.5f, 0, 0 }
};
float[,] kernelRAtGr = {
{ 0, 0, 0.5f, 0, 0 },
{ 0, -1, 0, -1, 0 },
{-1, 4, 5, 4, -1 },
{ 0, -1, 0, -1, 0 },
{ 0, 0, 0.5f, 0, 0 }
};
float[,] kernelRAtGb = {
{ 0, 0, -1, 0, 0 },
{ 0, -1, 4, -1, 0 },
{0.5f, 2, 5, 2, 0.5f },
{ 0, -1, 4, -1, 0 },
{ 0, 0, -1, 0, 0 }
};
// 归一化因子(根据Malvar原始论文)
float invKernelG = 1.0f / 8.0f;
float invKernelRAtB = 1.0f / 8.0f;
float invKernelRAtGr = 1.0f / 8.0f;
float invKernelRAtGb = 1.0f / 8.0f;
unsafe
{
float* extPtr = (float*)extended.Data;
int extStep = (int)extended.Step() / sizeof(float);
Vec3f* rgbPtr = (Vec3f*)rgb.Data;
int rgbStep = (int)rgb.Step() / sizeof(Vec3f);
// 并行处理每个像素
Parallel.For(0, height, y =>
{
int extY = y + 2;
for (int x = 0; x < width; x++)
{
int extX = x + 2;
int idx = y * rgbStep + x;
// 获取当前位置的颜色
char color = GetBayerColor(bayerPattern, y, x);
float center = extPtr[extY * extStep + extX];
float r = 0, g = 0, b = 0;
switch (color)
{
case 'R': // 红色像素位置
r = center;
g = ApplyKernel(extPtr, extStep, extY, extX, kernelG, invKernelG);
b = ApplyKernel(extPtr, extStep, extY, extX, kernelRAtB, invKernelRAtB);
break;
case 'B': // 蓝色像素位置
b = center;
g = ApplyKernel(extPtr, extStep, extY, extX, kernelG, invKernelG);
r = ApplyKernel(extPtr, extStep, extY, extX, kernelRAtB, invKernelRAtB);
break;
case 'G': // 绿色像素位置
g = center;
// 区分Gr和Gb位置
bool isGr = (bayerPattern == "RGGB" || bayerPattern == "GRBG") ?
(y % 2 == 0 && x % 2 == 1) : // RGGB: 奇数行偶数列
(y % 2 == 1 && x % 2 == 0); // GBRG: 偶数行奇数列
if (isGr) // Gr位置
{
r = ApplyKernel(extPtr, extStep, extY, extX, kernelRAtGr, invKernelRAtGr);
b = ApplyKernel(extPtr, extStep, extY, extX, kernelRAtB, invKernelRAtB);
}
else // Gb位置
{
r = ApplyKernel(extPtr, extStep, extY, extX, kernelRAtB, invKernelRAtB);
b = ApplyKernel(extPtr, extStep, extY, extX, kernelRAtGb, invKernelRAtGb);
}
break;
}
// 存储结果(OpenCV使用BGR顺序)
rgbPtr[idx] = new Vec3f(b, g, r);
}
});
}
// 转换为与输入相同位深的图像
Mat result = new Mat();
rgb.ConvertTo(result, raw.Type());
return result;
}
private static unsafe float ApplyKernel(float* src, int step, int y, int x,float[,] kernel, float scaleFactor)
{
float sum = 0;
for (int i = -2; i <= 2; i++)
{
for (int j = -2; j <= 2; j++)
{
float pixel = src[(y + i) * step + (x + j)];
sum += pixel * kernel[i + 2, j + 2];
}
}
return sum * scaleFactor;
}
// 辅助函数:获取拜耳阵列中的颜色
private static char GetBayerColor(string pattern, int row, int col)
{
// 计算模式索引 (0-3)
int index = (row % 2) * 2 + (col % 2);
return pattern[index];
}
最新发布