对比一下这个C# 的Demosaic和matlab的demosaic_malvar,我希望C#的处理结果要和matlab完全一样:public static Mat Demosaic(Mat raw, string bayerPattern)
{
// 确保输入为单通道图像
if (raw.Channels() != 1)
throw new ArgumentException("Input must be single-channel image");
int rows = raw.Rows;
int cols = raw.Cols;
// 创建拜耳掩模
Mat maskR = new Mat(rows, cols, MatType.CV_8UC1, Scalar.Black);
Mat maskGr = new Mat(rows, cols, MatType.CV_8UC1, Scalar.Black);
Mat maskGb = new Mat(rows, cols, MatType.CV_8UC1, Scalar.Black);
Mat maskB = new Mat(rows, cols, MatType.CV_8UC1, Scalar.Black);
// 根据拜耳模式设置掩模
switch (bayerPattern.ToLower())
{
case "rggb":
SetMask(maskR, 0, 0); // R: 偶行偶列
SetMask(maskGr, 0, 1); // Gr: 偶行奇列
SetMask(maskGb, 1, 0); // Gb: 奇行偶列
SetMask(maskB, 1, 1); // B: 奇行奇列
break;
case "grbg":
SetMask(maskGr, 0, 0); // Gr
SetMask(maskR, 0, 1); // R
SetMask(maskB, 1, 0); // B
SetMask(maskGb, 1, 1); // Gb
break;
case "gbrg":
SetMask(maskGb, 0, 0); // Gb
SetMask(maskB, 0, 1); // B
SetMask(maskR, 1, 0); // R
SetMask(maskGr, 1, 1); // Gr
break;
case "bggr":
SetMask(maskB, 0, 0); // B
SetMask(maskGb, 0, 1); // Gb
SetMask(maskGr, 1, 0); // Gr
SetMask(maskR, 1, 1); // R
break;
default:
throw new ArgumentException("Unsupported Bayer pattern. Use RGGB, GRBG, GBRG, or BGGR.");
}
// 转换输入图像为双精度浮点型
Mat rawDouble = new Mat();
raw.ConvertTo(rawDouble, MatType.CV_64FC1);
// 定义 Malvar 算法的卷积核 (5x5)
Mat kernelG = new Mat(5, 5, MatType.CV_64FC1, new double[,]
{
{ 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 }
}) / 8.0;
Mat kernelRB = new Mat(5, 5, MatType.CV_64FC1, new double[,]
{
{ 0, 0, -1.5, 0, 0 },
{ 0, 2, 0, 2, 0 },
{ -1.5, 0, 6, 0, -1.5 },
{ 0, 2, 0, 2, 0 },
{ 0, 0, -1.5, 0, 0 }
}) / 8.0;
Mat kernelRGr = new Mat(5, 5, MatType.CV_64FC1, new double[,]
{
{ 0, 0, 0.5, 0, 0 },
{ 0, -1, 0, -1, 0 },
{ -1, 4, 5, 4, -1 },
{ 0, -1, 0, -1, 0 },
{ 0, 0, 0.5, 0, 0 }
}) / 8.0;
Mat kernelRGb = new Mat(5, 5, MatType.CV_64FC1, new double[,]
{
{ 0, 0, -1, 0, 0 },
{ 0, -1, 4, -1, 0 },
{ 0.5, 0, 5, 0, 0.5 },
{ 0, -1, 4, -1, 0 },
{ 0, 0, -1, 0, 0 }
}) / 8.0;
// 初始化输出通道
Mat R = new Mat(rows, cols, MatType.CV_64FC1, Scalar.Black);
Mat G = new Mat(rows, cols, MatType.CV_64FC1, Scalar.Black);
Mat B = new Mat(rows, cols, MatType.CV_64FC1, Scalar.Black);
// === 绿色通道插值 ===
// 复制已知的绿色像素 (Gr 和 Gb)
rawDouble.CopyTo(G, maskGr);
rawDouble.CopyTo(G, maskGb);
// 在非绿色位置插值
Mat GInterp = new Mat();
Cv2.Filter2D(rawDouble, GInterp, MatType.CV_64FC1, kernelG,
anchor: new Point(-1, -1), delta: 0, borderType: BorderTypes.Replicate);
Mat maskGreen = maskGr | maskGb;
Mat maskNonGreen = new Mat();
Cv2.BitwiseNot(maskGreen, maskNonGreen);
GInterp.CopyTo(G, maskNonGreen);
// === 红色通道插值 ===
rawDouble.CopyTo(R, maskR); // 已知红色像素
// 在 Gr 位置插值红
Mat RGr = new Mat();
Cv2.Filter2D(rawDouble, RGr, MatType.CV_64FC1, kernelRGr,
anchor: new Point(-1, -1), borderType: BorderTypes.Replicate);
RGr.CopyTo(R, maskGr);
// 在 Gb 位置插值红
Mat RGb = new Mat();
Cv2.Filter2D(rawDouble, RGb, MatType.CV_64FC1, kernelRGb,
anchor: new Point(-1, -1), borderType: BorderTypes.Replicate);
RGb.CopyTo(R, maskGb);
// 在 B 位置插值红
Mat RB = new Mat();
Cv2.Filter2D(rawDouble, RB, MatType.CV_64FC1, kernelRB,
anchor: new Point(-1, -1), borderType: BorderTypes.Replicate);
RB.CopyTo(R, maskB);
// === 蓝色通道插值 ===
rawDouble.CopyTo(B, maskB); // 已知蓝色像素
// 在 Gr 位置插值蓝 (使用 RGb 核)
Mat BGr = new Mat();
Cv2.Filter2D(rawDouble, BGr, MatType.CV_64FC1, kernelRGb,
anchor: new Point(-1, -1), borderType: BorderTypes.Replicate);
BGr.CopyTo(B, maskGr);
// 在 Gb 位置插值蓝 (使用 RGr 核)
Mat BGb = new Mat();
Cv2.Filter2D(rawDouble, BGb, MatType.CV_64FC1, kernelRGr,
anchor: new Point(-1, -1), borderType: BorderTypes.Replicate);
BGb.CopyTo(B, maskGb);
// 在 R 位置插值蓝 (使用 RB 核)
Mat BR = new Mat();
Cv2.Filter2D(rawDouble, BR, MatType.CV_64FC1, kernelRB,
anchor: new Point(-1, -1), borderType: BorderTypes.Replicate);
BR.CopyTo(B, maskR);
// 四舍五入到整数
Mat RInt = RoundMat(R);
Mat GInt = RoundMat(G);
Mat BInt = RoundMat(B);
// 合并通道并返回
Mat[] channels = { RInt, GInt, BInt };
Mat result = new Mat();
Cv2.Merge(channels, result);
return result;
}
// 辅助函数:设置拜耳掩模
private static void SetMask(Mat mask, int rowStart, int colStart)
{
for (int r = rowStart; r < mask.Rows; r += 2)
{
for (int c = colStart; c < mask.Cols; c += 2)
{
mask.At<byte>(r, c) = 255;
}
}
}
// 辅助函数:四舍五入矩阵值
private static Mat RoundMat(Mat src)
{
Mat dst = new Mat();
src.ConvertTo(dst, MatType.CV_32S); // 四舍五入到整数
dst.ConvertTo(dst, MatType.CV_64FC1); // 转回双精度
return dst;
}
function rgb = demosaic_malvar(raw_matrix, bayerPattern)
% 确保输入是双精度
raw_matrix = double(raw_matrix);
[rows, cols] = size(raw_matrix);
% 创建精确的逻辑型拜耳掩模 (RGGB)
mask_R = false(rows, cols);
mask_Gr = false(rows, cols);
mask_Gb = false(rows, cols);
mask_B = false(rows, cols);
% 根据bayerPattern设置掩模
switch lower(bayerPattern)
case 'rggb'
% RGGB模式
mask_R(1:2:end, 1:2:end) = true;
mask_Gr(1:2:end, 2:2:end) = true;
mask_Gb(2:2:end, 1:2:end) = true;
mask_B(2:2:end, 2:2:end) = true;
case 'grbg'
% GRBG模式
mask_Gr(1:2:end, 1:2:end) = true;
mask_R(1:2:end, 2:2:end) = true;
mask_B(2:2:end, 1:2:end) = true;
mask_Gb(2:2:end, 2:2:end) = true;
case 'gbrg'
% GBRG模式
mask_Gb(1:2:end, 1:2:end) = true;
mask_B(1:2:end, 2:2:end) = true;
mask_R(2:2:end, 1:2:end) = true;
mask_Gr(2:2:end, 2:2:end) = true;
case 'bggr'
% BGGR模式
mask_B(1:2:end, 1:2:end) = true;
mask_Gb(1:2:end, 2:2:end) = true;
mask_Gr(2:2:end, 1:2:end) = true;
mask_R(2:2:end, 2:2:end) = true;
otherwise
error('Unsupported Bayer pattern. Use RGGB, GRBG, GBRG, or BGGR.');
end
% 精确的Malvar卷积核
kernel_G = [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] / 8;
kernel_R_B = [0, 0, -1.5, 0, 0;
0, 2, 0, 2, 0;
-1.5, 0, 6, 0, -1.5;
0, 2, 0, 2, 0;
0, 0, -1.5, 0, 0] / 8;
kernel_R_Gr = [0, 0, 0.5, 0, 0;
0, -1, 0, -1, 0;
-1, 4, 5, 4, -1;
0, -1, 0, -1, 0;
0, 0, 0.5, 0, 0] / 8;
kernel_R_Gb = [0, 0, -1, 0, 0;
0, -1, 4, -1, 0;
0.5, 0, 5, 0, 0.5;
0, -1, 4, -1, 0;
0, 0, -1, 0, 0] / 8;
% 蓝在Gr位置 (与红在Gb相同)
kernel_B_Gr = kernel_R_Gb;
% 蓝在Gb位置 (与红在Gr相同)
kernel_B_Gb = kernel_R_Gr;
% 蓝在R位置 (专用核,与红在B位置相同)
kernel_B_R = kernel_R_B;
% 初始化通道
R = zeros(rows, cols);
G = zeros(rows, cols);
B = zeros(rows, cols);
% === 绿色通道插值 ===
G(mask_Gr | mask_Gb) = raw_matrix(mask_Gr | mask_Gb);
G_interp = imfilter(raw_matrix, kernel_G, 'replicate', 'conv');
G(mask_R | mask_B) = G_interp(mask_R | mask_B);
% === 红色通道插值 ===
R(mask_R) = raw_matrix(mask_R);
R_Gr = imfilter(raw_matrix, kernel_R_Gr, 'replicate', 'conv');
R(mask_Gr) = R_Gr(mask_Gr);
R_Gb = imfilter(raw_matrix, kernel_R_Gb, 'replicate', 'conv');
R(mask_Gb) = R_Gb(mask_Gb);
R_B = imfilter(raw_matrix, kernel_R_B, 'replicate', 'conv');
R(mask_B) = R_B(mask_B);
% === 蓝色通道插值 ===
B(mask_B) = raw_matrix(mask_B);
B_Gr = imfilter(raw_matrix, kernel_B_Gr, 'replicate', 'conv');
B(mask_Gr) = B_Gr(mask_Gr);
B_Gb = imfilter(raw_matrix, kernel_B_Gb, 'replicate', 'conv');
B(mask_Gb) = B_Gb(mask_Gb);
B_R = imfilter(raw_matrix, kernel_B_R, 'replicate', 'conv');
B(mask_R) = B_R(mask_R);
% 四舍五入并组合RGB图像
R = round(R);
G = round(G);
B = round(B);
rgb = cat(3, R, G, B);
end
最新发布