Moire Pattern以及解决方式

本文探讨了图像学中的干涉纹理现象,特别是黑白棋盘格透视渲染时出现的问题。干涉纹理是由于图像中的线状材质在远处渲染时产生的失真。文章提供了两种解决方案:采用抗锯齿技术和调整材质大小。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

标题的英文中文中叫干涉纹理,症状如下:



注:图片都来自于网络


在图像学中,常用那个黑白棋盘的透视渲染来引出这个问题。这个问题的根本原因是图像中含有“线状”的材质,当渲染取样的时候,材质出现远处部分会出现这种干涉现象。


解决这个图像失真的方式,

1、用抗锯齿;

2、把材质缩小;

这个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]; }
最新发布
07-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值