如何在OpenCV2中高效创建二进制网格矩阵?及图像resize补零方案问询
高效棋盘格矩阵创建与图像2倍放大填0方案
嘿,我来帮你搞定这两个需求:先说说更高效的棋盘格二进制矩阵实现,再给你直接实现图像2倍放大且空缺处填0的方法~
一、更高效的棋盘格矩阵实现
你当前的思路没问题,但可以从内存和准确性上优化,尤其是避免不必要的类型浪费:
优化版基础块重复法
// 用uchar类型替代double,更贴合0/255的二进制场景,内存占用仅1/8 Mat tmp = (Mat_<uchar>(2, 2) << 255, 0, 0, 255); // 注意OpenCV的repeat参数是「行重复次数,列重复次数」,你之前的cols/rows顺序搞反啦! Mat bwMask = cv::repeat(tmp, rows / 2, cols / 2); // 处理行数/列数为奇数的情况,补全最后一行/列 if (rows % 2 != 0) { Mat lastRow = bwMask.row(0).clone(); vconcat(bwMask, lastRow, bwMask); } if (cols % 2 != 0) { Mat lastCol = bwMask.col(0).clone(); hconcat(bwMask, lastCol, bwMask); }
为什么更高效?
uchar比double节省75%内存,重复复制时运算更快- 修正了
repeat的参数顺序,避免生成的棋盘格列行颠倒
超大矩阵首选:逐行直接生成
如果要生成的矩阵特别大,没必要先创建小方块再重复,直接原地生成更省内存:
Mat bwMask(rows, cols, CV_8UC1); for (int i = 0; i < rows; ++i) { uchar* rowPtr = bwMask.ptr<uchar>(i); for (int j = 0; j < cols; ++j) { // 棋盘格核心逻辑:行号+列号为偶数时设255,奇数设0(反过来也可以,看你需求) rowPtr[j] = (i + j) % 2 == 0 ? 255 : 0; } }
这种方法不用临时矩阵,还能自动适配奇数行/列,不用额外补全。
二、直接实现图像2倍放大且空缺处填0
你想要的是把图像放大到2倍,跳过插值,直接把原像素放在对应位置,其余空缺填0?分两种场景给你方案:
场景1:原像素占(2i,2j),其余位置全为0
最直接的循环实现,精准控制每个像素位置:
Mat src; // 你的输入图像 // 初始化目标图像为全0 Mat dst(2 * src.rows, 2 * src.cols, src.type(), Scalar(0)); for (int i = 0; i < src.rows; ++i) { const uchar* srcRow = src.ptr<uchar>(i); // 获取目标图像的第2i行指针(2i+1行全是0,不用处理) uchar* dstRowEven = dst.ptr<uchar>(2 * i); for (int j = 0; j < src.cols; ++j) { // 把原像素复制到目标图像的(2i,2j)位置 dstRowEven[2 * j] = srcRow[j]; } }
场景2:结合棋盘格,原像素放在棋盘格的255位置
如果是要让放大后的图像和棋盘格对应,只在白块保留原像素,黑块填0,可以这么做:
Mat src; // 输入图像 Mat srcScaled; // 先用最近邻插值把图像放大2倍(让每个原像素复制到2x2区域) resize(src, srcScaled, Size(2 * src.cols, 2 * src.rows), 0, 0, INTER_NEAREST); // 创建和放大后图像同尺寸的棋盘格掩码 Mat mask(srcScaled.rows, srcScaled.cols, CV_8UC1); for (int i = 0; i < mask.rows; ++i) { uchar* row = mask.ptr<uchar>(i); for (int j = 0; j < mask.cols; ++j) { // i/2和j/2让原图像的每个像素对应棋盘格的一个2x2块 row[j] = (i/2 + j/2) % 2 == 0 ? 255 : 0; } } // 把掩码为0的位置的像素置0 srcScaled.setTo(0, mask == 0);
内容的提问来源于stack exchange,提问作者Newb
相关产品推荐
相关产品推荐

