[C++] 如何使用opencv进行大图像的切割

27 篇文章 1 订阅

关于源代码

源代码和用到的支持超过1G像素大小的opencv库(vc17+vs2022)已经上传到csdn,可以通过博文的标题下方提供连接进行下载。

创作背景

最近在做一个电路底板的缺陷检测项目,线扫相机保存下来的bmp图像大概为1.5G,像素大小为30000+ x 80000+,在进行缺陷分析之前,需要把bmp大图先切成1280x1280或者640x640的小图,然后在小图上使用yolov8进行缺陷分析。

本文将会介绍如何通过opencv大的bmp图像,切换成1280 x 1280的小图。

开发思路

通过opencv从本地读取bmp图像,然后在按照输入的图像尺寸进行图像分割,一边分割一边按照一定的命名规则来把小图保存到本地目录。

源代码

#include <filesystem>
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;
namespace fs = std::filesystem;

/**
 * src: image matix from opencv for cut.
 * subWidth: The width for sub image.
 * subHeight: The height for sub image.
 * subSaveDir: The save directory for sub images.
 * subImgNamePrefix: The prefix for sub image.
 * subImgNameExt: The extension name for sub image.
 * clearSubImages: The flag to clear the old sub images in subSaveDir or not.
*/
int cutImage(Mat& src, int subWidth, int subHeight, const cv::String& subSaveDir="./cut_images",
const cv::String& subImgNamePrefix="", const cv::String subImgNameExt=".jpg", bool clearSubImages=false)
{
    if (!fs::is_directory(subSaveDir)){
        std::cerr << "save dir is not a directory." << std::endl;
        return -1;
    }
    if(clearSubImages && fs::exists(subSaveDir)){
        fs::remove_all(subSaveDir);
        std::cout << "clear sub dir:" << subSaveDir << std::endl;
    }
    if (!fs::exists(subSaveDir)){
        fs::create_directories(subSaveDir);
        std::cout << "create save dir:" << subSaveDir  << std::endl;
    }

	int srcHeight, srcWidth, subImageNumY, subImageNumX;
	srcHeight = src.rows; 
    srcWidth = src.cols;
	subImageNumY = srcHeight / subHeight;
	if (srcHeight % subHeight > 0) {
		subImageNumY += 1;
	}
	subImageNumX = srcWidth / subWidth;
	if (srcWidth % subWidth > 0) {
		subImageNumX += 1;
	}
	std::cout << "y count:" << subImageNumY << ",x count:" << subImageNumX << ", total:" << subImageNumY * subImageNumX << std::endl;
    int failCount = 0;
	for (int j = 0; j < subImageNumY; j++)
	{
		for (int i = 0; i < subImageNumX; i++)
		{
			int endWidth = std::min((i + 1) * subWidth, srcWidth);
			int endHeight = std::min((j + 1) * subHeight, srcHeight);
			Mat imageROI = src(Range(j * subHeight, endHeight), Range(i * subWidth, endWidth));
			std::cout << "y:" << j << ", x:" << i << std::endl;
            //输出保存各子图像
			string subImgName = subImgNamePrefix + std::to_string(j) + "_" + std::to_string(i) + subImgNameExt; 
            fs::path subSavePath;
            subSavePath.append(subSaveDir);
            subSavePath.append(subImgName);
			if(!imwrite(subSavePath.string(), imageROI)){
                std::cerr << "save sub image failure. sub_img_path: " << subSavePath.string() << std::endl;
                failCount ++;
            };
		}
	}
    std::cout << "total: " << subImageNumY * subImageNumX << ", fail: " << failCount << std::endl;
    return 0;
}

int main(int argc,char **argv){
    // ./cut_image.exe D:/LearnFlawDetect/CLearnFlawDetect/CircleCut/Images/camera_3.bmp 1280 ./camera_3
    if (argc < 4){
        std::cerr << "格式错误. 请使用正确格式 'cut_image.exe 要切割的bmp的路径 切割的子图的大小 切割的子图的保存路径'" << std::endl; 
        return -1;
    }
    try{
        char *srcImgPath = argv[1];
        int cutImgSize = std::stoi(argv[2]);
        if (cutImgSize < 320 || cutImgSize > 640 * 2){
            std::cerr << "sub img size must >=320 and <=1280" << std::endl;
            return -1;
        }
        char *saveImgDir = argv[3];
        std::cout << "src_img_path:" << srcImgPath << ", cut_img_size:" << cutImgSize << ", save_dir:" << saveImgDir << std::endl;
        Mat grayImg = imread(srcImgPath, IMREAD_GRAYSCALE);
        if (!grayImg.empty()) {
            std::cout << "shape:" << grayImg.rows << "," << grayImg.cols << std::endl;
            cutImage(grayImg, cutImgSize, cutImgSize, saveImgDir, "", ".jpg", true);
        }
        return 0;
    }catch( Exception e){
        std::cerr << "发生异常. 异常信息:" << e.what() << std::endl;
        return -1;
    }
}

如何运行

运行环境

Windows10 + CMake +  VS 2022(C++17) 

安装CMake

如何安装Cmake, 可以参考另一篇文章:

[CMake] 基础教程 - CMake安装和验证测试(Windows+Linux)

安装VS 2022社区版

如何安装VS 2022社区版,参考另一篇文章:

[Visual Studio] 基础教程 - Window10下如何安装VS 2022社区版

安装和配置opencv

关于如何安装,可以参考另一篇文章:

[C++] 详细教程 - opencv4.8.0安装和验证测试 (Windows + Linux)

因为需要读取的bmp图像超过了1G,默认从官网下载的库读取超过1G的图像是会报错的,如何解决这个问题,可以参考另一篇文章:

[C++] 问题分析和解决 - 如何使用opencv处理大于1G的bmp图像

下载源代码并解压

通过CMake来构建项目

# 通过控制台你的解压目录
cmake -S . -B build
cmake --build build

通过命令行窗口运行

进阶探讨

因为图像比较大,会切割出1000+的小图,后续考虑增加多线程来进行切割和保存,整体提升一下运行的速度。

  • 12
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 利用OpenCV进行图像识别是一种常见的计算机视觉应用。OpenCV是一个开源计算机视觉库,支持多种编程语言,包括C++、Python等。它提供了丰富的图像处理和计算机视觉算法,可以用来进行图像识别、目标检测、人脸识别、手势识别等任务。 在进行图像识别时,首先需要加载和处理图像OpenCV提供了读取、保存和处理图像的函数,可以对图像进行灰度化、二值化、滤波等预处理操作,以提高后续识别的准确性。 接下来,可以使用OpenCV提供的特征提取算法,如SIFT、SURF、HOG等,来提取图像的特征。这些算法可以提取出图像中的关键特征点或特征向量,用于识别或匹配。 然后,可以使用OpenCV提供的机器学习算法,如支持向量机(SVM)、K最近邻(KNN)等,来训练一个分类器或回归器。通过给分类器提供一系列已知的图像样本和其对应的标签,可以训练模型,使其可以自动识别未知图像。 最后,可以使用训练好的模型对新的图像进行识别。将新的图像输入到分类器中,分类器将输出一个标签,表示图像所属的类别。根据这个标签,可以判断图像中的物体或场景是什么。 总之,利用OpenCV进行图像识别可以实现多种应用,如车牌识别、人脸识别、文字识别等。通过选择合适的图像处理和机器学习算法,可以有效提高图像识别的准确性和效率。 ### 回答2: OpenCV是一个开源的计算机视觉库,常用于图像处理和计算机视觉任务。使用OpenCV进行图像识别可以通过以下步骤实现。 1. 导入OpenCV库:首先需要安装并导入OpenCV库,确保可以在代码中使用相关函数和类。 2. 加载图像使用OpenCV的函数或方法加载待识别的图像文件。可以通过指定文件路径或者从摄像头实时获取图像。 3. 图像预处理:在进行图像识别之前,通常需要进行一些预处理操作。比如调整图像大小、灰度化处理、去除噪声等。这些预处理操作有助于提高识别准确率和效果。 4. 特征提取:通过OpenCV提供的函数或方法,从图像中提取出有用的特征信息。这些特征可以是图像的边缘、角点、颜色直方图等等,可以根据具体任务选择合适的特征。 5. 训练模型:使用提取出的特征数据,训练一个机器学习模型或者深度学习模型。可以选择使用OpenCV的机器学习模块,也可以使用其他深度学习框架如TensorFlow、PyTorch等。 6. 图像识别:使用训练好的模型对新的图像进行识别。将预处理和特征提取应用到待识别图像上,然后输入到模型中进行识别。根据不同的任务,可以得到不同的识别结果,比如物体识别、手势识别、人脸识别等。 7. 分析结果:根据识别结果进行分析,可以对图像内容进行标记、分类、计数等处理。根据具体需求,可以输出结果图像、生成报告或者执行其他进一步的操作。 总之,通过使用OpenCV进行图像识别,可以实现从加载图像到预处理、特征提取、模型训练和图像识别的完整过程,提供了强大的工具和函数库来支持各种图像识别任务。通过合理的处理和使用相关技术,可以实现高效准确的图像识别应用。 ### 回答3: OpenCV是一个开源的计算机视觉库,可以帮助我们进行图像和视频处理。通过使用OpenCV,我们可以实现图像识别的功能。 在使用OpenCV进行图像识别时,我们可以首先加载并读取待识别的图像。然后,可以应用不同的技术和算法对图像进行处理和分析。例如,我们可以使用特征提取算法,如SIFT(尺度不变特征变换)或SURF(加速稳健特征),来提取图像中的关键点和特征描述符。然后,可以使用这些特征描述符进行匹配,以识别图像中的物体或场景。 另外,我们还可以使用机器学习算法来训练图像分类器,以识别不同类别的图像。对于训练图像分类器,我们需要准备一组已标记的图像数据集,然后使用OpenCV提供的机器学习算法,如支持向量机(SVM)或卷积神经网络(CNN),进行训练和优化。训练完成后,我们就可以使用这个分类器对新的未知图像进行分类和识别。 此外,OpenCV还提供了其他功能,如人脸识别、目标跟踪、图像分割等。通过使用这些功能,我们可以进一步提高图像识别的准确性和性能。 综上所述,利用OpenCV进行图像识别可以通过特征提取和匹配、机器学习分类器等技术来实现。OpenCV作为一个强大的计算机视觉库,为我们提供了丰富的工具和算法,方便我们进行图像识别和处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老狼IT工作室

你的鼓励将是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值