前言

最近开始做这个裂缝识别的任务了,大大小小的问题我已经摸得差不多了,然后关于识别任务和分割任务我现在也弄的差不多了。

现在开始做正式的业务,也就是我们说的裂缝识别的任务。作为前言,先来说说场景:

现在相机返回过来的照片:

  1. 都是jpeg格式的照片,当然也可能是别的格式,目前主流是jpeg格式
  2. 大小约为11mb-14mb左右
  3. 图片大小为5120x5120

我们现在如果说想直接使用这个图片来进行图片识别的话,会有很多的问题。其中最主要的问题就是图片实在是过大,5120x5120的图片会导致图片不论是训练还是推理期都太长了,并且为了更好地处理图片,我们都会要求图片的训练期和推断图片都必须是比较小的,这样才有利于我们后续不论是实例分割还是目标识别任务。

目标

前言说了,我们的目标主要是两个,那就是

  1. 将现有图片分割成1280 * 1280 的小块。

    为什么这么做?因为我们的图片边界刚好是5120,5120 / 4 = 1280,也就是说我们要把原先一张照片切成 4 * 4 = 16块

  2. 将现有图片全部增亮

    这里需要注意一点,就是在增亮图片的同时,不能让图片过曝。这里我们需要做一点特殊的处理,下文中会说。

准备

既然有了目标,那么我们就来一步步写实现。这里因为我们后续要使用opencv等各种库,所以从现在开始我们所有的c++项目统一使用cmake管理。

那么在正式开始之前,我们需要准备opencv环境

这里可以参考以下文章

windows下安装Visual Studio + CMake+OpenCV + OpenCV contrib+TensorRT

有关cmake编译与安装opencv的内容,我觉得是比较中肯的,这里因为我已经安装好了opencv,就不再重复这个内容了。

那么现在默认就是大伙已经安装上了opencv 了,那么我这里就开始写图像分割和增强了。

首先使用vs 2022新建一个cmake项目:

创建完毕后,打开cmake gui程序



这里我使用vs 2022来编译和管理这个项目,点击configure,然后再点击gernerate,这样一个空项目就被我编辑出来了,就在我们的build目录下

点击Lev_PictureManager.sln进入项目管理。



当然了,我这里开发的这个工程是需要以后去做移植的,所以肯定是做成dll的,这个有关图形的库后续我也会做一些更新,相当于是一个自己的小工具箱,所以为了更好的使用这里需要修改一下 cmake 工程

Lev_PictureManager的CMakeList.txt改成这样,每一条为什么这么改我都写在了注释里面,可以看看

# CMakeList.txt: Lev_PictureManager 的 CMake 项目,在此处包括源代码并定义
# 项目特定的逻辑。
#
#如果环境变量中没有声明opencv的路径则需要加上这一条,如果加上了则无所谓
set(OpenCV_DIR C:\\Program Files (x86)\\opencv\\build)
#找到opencv 的 package
find_package(OpenCV REQUIRED)
#引入opencv的头文件
include_directories(${OpenCV_INCLUDE_DIRS})
#导出windows下的.lib静态链接库用以链接符号
set(WINDOWS_EXPORT_ALL_SYMBOLS ON)
# 导出为动态链接库的形式
add_library (Lev_PictureManager SHARED "Lev_PictureManager.cpp" "Lev_PictureManager.h")
#链接到opencv的.lib文件
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBRARIES}) if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET Lev_PictureManager PROPERTY CXX_STANDARD 20)
endif() # TODO: 如有需要,请添加测试并安装目标。

接下来在项目中编译一下这个CMakeList.txt,再尝试在头文件中引入

#include "opencv2/opencv.hpp"

如果引入成功,则说明调用是成功的,接下来就可以进入正式的 编码阶段了

流程

我们之前说的有两个内容,一个是切分图片,一个是提升亮度

切分图片

切分图片的话,主要是用到了opencv的Rect来对roi切分,具体思路见下代码:

	std::vector<cv::Mat> splitImage(const cv::Mat& inputImage, int rows, int cols) {
std::vector<cv::Mat> subImages; int subImageWidth = inputImage.cols / cols;
int subImageHeight = inputImage.rows / rows; for (int y = 0; y < rows; ++y) {
for (int x = 0; x < cols; ++x) {
// 定义矩形区域,切分图像
cv::Rect roi(x * subImageWidth, y * subImageHeight, subImageWidth, subImageHeight); // 获取子图像
cv::Mat subImage = inputImage(roi).clone(); // 添加到结果集
subImages.push_back(subImage);
}
} return subImages;
}

修改亮度

	cv::Mat enhanceBrightnessImage(const cv::Mat& image) {
// 转换为YUV颜色空间
cv::Mat imgYUV;
cv::cvtColor(image, imgYUV, cv::COLOR_BGR2YUV); // 应用CLAHE到Y通道(YUV中的Y代表亮度)
cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE(2.0, cv::Size(8, 8));
clahe->apply(0, imgYUV); // 修正此行代码 // 将结果转换回BGR格式
cv::Mat imgOutput;
cv::cvtColor(imgYUV, imgOutput, cv::COLOR_YUV2BGR); return imgOutput;
}

项目整体代码如下:

头文件Lev_PictureManager.h

// Lev_PictureManager.h: 标准系统包含文件的包含文件
// 或项目特定的包含文件。 #pragma once #include <iostream>
// TODO: 在此处引用程序需要的其他标头。
#include "filesystem"
#include "opencv2/opencv.hpp" namespace Lev_PictureManager {
/// <summary>
/// 判断文件后缀是否为支持的图片
/// </summary>
/// <param name="extension">传入后缀,支持输入.jpg .png .jpeg</param>
/// <returns>是否支持</returns>
bool isImageFileExtend(const std::string extension);
/// <summary>
/// 缩放图片大小到指定大小
/// </summary>
/// <param name="insertPath">输入图片的绝对路径,包括图片名称</param>
/// <param name="outputPath">输出图片的绝对路径,包括图片名称</param>
/// <param name="tar_width">目标缩放宽度</param>
/// <param name="tar_height">目标缩放高度</param>
/// <returns>成功与否</returns>
bool ResizeSingleImage(const std::string& insert_picture, const std::string& output_path, int tar_width, int tar_height); /// <summary>
/// 将指定图片路径输入,导到指定目录中去
/// </summary>
/// <param name="insert_picture">输入图片路径</param>
/// <param name="output_path">输出分裂图片的路径</param>
/// <param name="row">指定切分行数</param>
/// <param name="col">指定切分列数</param>
/// <param name="suffix">后缀,默认是_,不同的图片会在指定后缀后,加上row-col的后缀比如 test_1-12.jpeg</param>
/// <returns>是否切分成功</returns>
bool TearPicture(const std::string& insert_picture, const std::string& output_path, int row, int col,const std::string& suffix); /// <summary>
/// 调整图片亮度到最佳
/// </summary>
/// <param name="input_picture">输入图片的路径</param>
/// <param name="output_path">图片输出路径</param>
/// <returns></returns>
bool adjustBrightness(const std::string& input_picture, const std::string& output_path); }

Lev_PictureManager.cpp

// Lev_PictureManager.cpp: 定义应用程序的入口点。
// #include "Lev_PictureManager.h"
using namespace std;
namespace fs = std::filesystem;
//使用命名空间是一种美德:D
namespace Lev_PictureManager {
bool isImageFileExtend(const std::string extension){
// 在这里添加你需要支持的图片格式的判断条件
return extension == ".jpg" || extension == ".png" || extension == ".jpeg";
} bool ResizeSingleImage(const std::string& insertPath, const std::string& outputPath, int tar_width, int tar_height) {
cv::Mat originalImage = cv::imread(cv::String(insertPath), cv::IMREAD_COLOR);
cv::String outString = cv::String(outputPath);
if (originalImage.empty()) {
std::cerr << "Failed to open image!" << std::endl;
return false;
} // 获取原始图像的宽高
int originalWidth = originalImage.cols;
int originalHeight = originalImage.rows; // 计算缩放比例
double scaleWidth = static_cast<double>(tar_width) / originalWidth;
double scaleHeight = static_cast<double>(tar_height) / originalHeight; // 使用 resize 函数进行缩放
cv::Mat resizedImage;
cv::resize(originalImage, resizedImage, cv::Size(), scaleWidth, scaleHeight, cv::INTER_LINEAR); // 保存压缩后的图像
if (!cv::imwrite(outString, resizedImage)) return false;
return true;
} std::vector<cv::Mat> splitImage(const cv::Mat& inputImage, int rows, int cols) {
std::vector<cv::Mat> subImages; int subImageWidth = inputImage.cols / cols;
int subImageHeight = inputImage.rows / rows; for (int y = 0; y < rows; ++y) {
for (int x = 0; x < cols; ++x) {
// 定义矩形区域,切分图像
cv::Rect roi(x * subImageWidth, y * subImageHeight, subImageWidth, subImageHeight); // 获取子图像
cv::Mat subImage = inputImage(roi).clone(); // 添加到结果集
subImages.push_back(subImage);
}
} return subImages;
}
bool TearPicture(const std::string& insert_picture, const std::string& output_path, int row, int col, const std::string& suffix)
{
//判断输入图片是否是支持的文件
fs::path insertPath(insert_picture);
if(!fs::is_regular_file(insertPath)) return false;
if(!isImageFileExtend(insertPath.extension().string())) return false; //不带后缀的后缀名
std::string insert_picture_name = insertPath.stem().string(); //将图片切分成vector
cv::Mat mat_insert = cv::imread(insert_picture); std::vector<cv::Mat> vec_ret = splitImage(mat_insert, row, col); //将vector中的图片保存到指定路径
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
std::string output_name = output_path + "/" + insert_picture_name + "_" + std::to_string(i) + "-" + std::to_string(j) + "." + suffix;
if (!cv::imwrite(output_name, vec_ret[i + j])) return false;
}
} return true;
} cv::Mat enhanceBrightnessImage(const cv::Mat& image) {
// 转换为YUV颜色空间
cv::Mat imgYUV;
cv::cvtColor(image, imgYUV, cv::COLOR_BGR2YUV); // 应用CLAHE到Y通道(YUV中的Y代表亮度)
cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE(2.0, cv::Size(8, 8));
clahe->apply(0, imgYUV); // 修正此行代码 // 将结果转换回BGR格式
cv::Mat imgOutput;
cv::cvtColor(imgYUV, imgOutput, cv::COLOR_YUV2BGR); return imgOutput;
} bool adjustBrightness(const std::string& input_picture, const std::string& output_path)
{
//判断输入图片是否是支持的文件
fs::path insertPath(input_picture);
if (!fs::is_regular_file(insertPath)) return false;
if (!isImageFileExtend(insertPath.extension().string())) return false; std::string input_filename = insertPath.filename().string();
std::string output_filename = output_path + "/" + input_filename;
cv::Mat mat_input = cv::imread(input_picture);
cv::Mat mat_output = enhanceBrightnessImage(mat_input); if (!cv::imwrite(output_filename, mat_output)) return false;
return true;
} }

完整工程(带Demo)见本人Github:

LeventureQys/Lev_PictureManager

全流程机器视觉工程开发(三)任务前瞻 - 从opencv的安装编译说起,到图像增强和分割的更多相关文章

  1. 全球首个全流程跨平台界面开发套件,PowerUI分析

    一.       首个全流程跨平台界面开发套件,PowerUI正式发布 UIPower在DirectUI的基础上,自主研发全球首个全流程跨平台界面开发套件PowerUI(PUI)正式发布,PowerU ...

  2. halcon机器视觉工程开发思路

    参考:halcon学习笔记——机器视觉工程应用的开发思路https://www.cnblogs.com/hanzhaoxin/archive/2013/02/15/2912879.html

  3. CentOS7+CDH5.14.0安装全流程记录,图文详解全程实测-1虚拟机安装及环境初始化

    1.软件准备: VMware-workstation-full-14.1.2-8497320.exe CentOS-7-x86_64-DVD-1804.iso 2.VMare激活码: AU5WA-0E ...

  4. CentOS7+CDH5.14.0安装全流程记录,图文详解全程实测-总目录

    CentOS7+CDH5.14.0安装全流程记录,图文详解全程实测-总目录: 0.Windows 10本机下载Xshell,以方便往Linux主机上上传大文件 1.CentOS7+CDH5.14.0安 ...

  5. Ubuntu下opencv的安装及IDEA开发配置

    Ubuntu下opencv的安装及IDEA开发配置 环境配置  这篇博客主要介绍Ubuntu下opencv的安装编译,以及IDEA对opencv进行Java开发的环境配置 安装opencv 首先安装o ...

  6. 十分钟带你了解CANN应用开发全流程

    摘要:CANN作为昇腾AI处理器的发动机,支持业界多种主流的AI框架,包括MindSpore.TensorFlow.Pytorch.Caffe等,并提供1200多个基础算子. 2021年7月8日,第四 ...

  7. AI全流程开发难题破解之钥

    摘要:通过对ModelArts.盘古大模型.ModelBox产品技术的解读,帮助开发者更好的了解AI开发生产线. 本文分享自华为云社区<[大厂内参]第16期:华为云AI开发生产线,破解AI全流程 ...

  8. Halcon学习笔记——机器视觉应用工程开发思路及相机标定

    机器视觉应用工程开发思路 机器视觉应用工程主要可划分为两大部分,硬件部分和软件部分. 1.硬件部分,硬件的选型至关重要,决定了后续工作是否可以正常开展,其中关键硬件部分包括:光源,相机以及镜头. 2. ...

  9. 基于Jenkins的开发测试全流程持续集成实践

    今年一直在公司实践CI,本文将近半年来的一些实践总结一下,可能不太完善或优美,但的确初步解决了我目前所在项目组的一些痛点.当然这仅是一家之言也不够完整,后续还会深入实践和引入Kubernetes进行容 ...

  10. “全栈2019”Java第三章:安装开发工具IntelliJ IDEA

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

随机推荐

  1. AtCoder Educational DP Contest 刷题记录

    写在前面 深感自己 DP 很弱的 村人B 刷了点 DP 题,题集地址戳这里. 后记:刷完后感觉自己又行了 A - Frog 1 题意 给定 \(n\) 个石头,第 i 个石头的高度为 \(h_i\). ...

  2. debian更新openssh 9.6

    先更新一下,然后安装libssl-dev zlib1g-dev依赖文件 apt update apt install build-essential apt-get install -y libssl ...

  3. 制作PE工具箱

    事前准备: 能上网的电脑 x1 台 大于8G的U盘 x一个(如果需要储存安装镜像的话,如果不需要的话大于1G即可) 一.下载PE工具箱 推荐使用WEPE工具箱,无广告无推广.不推荐老X桃,大X菜,大X ...

  4. C#格式化输入数据为货币格式

    private void btn_Get_Click(object sender, EventArgs e) { double P_dbl_value;//定义double类型变量 if (doubl ...

  5. 万字血书Vue—Vue的核心概念

    MVVM M:模型(Model):data V:视图(View):模板 VM:视图模型(ViewModel):Vue实例对象 Vue收到了MVVM模型的启发,MVVM是vue实现数据驱动视图和双向数据 ...

  6. Memory Bist

    SRAMC主要是对SRAM进行控制 对于SRAM的逻辑,根据地址将数据存储到SRAM中,然后根据地址将SRAM中的数据读取出来 如何测试Memory,生产工艺原因造成的问题,采用DFT或者Bist测试 ...

  7. SQLServer命令行备份数据库

    SQLServer命令行备份数据库 背景 SQLServer on linux 想设置计划任务自动备份数据库 感觉sqlcmd应该是最简单快捷的方式了 所以进行一下处理. 安装必备软件 sudo cu ...

  8. Oracle 高低水位线的学习

    Oracle 高低水位线的学习 背景 最近产品的一些脚本会大量的给一些流程表里面插入数据 因为只是一个流程相关没有时序查询的需求 所以数据量挺大, 但是按照石时间戳删除非常麻烦. 自己执行过多次del ...

  9. [转帖]linux之iftop命令

    https://rumenz.com/rumenbiji/linux-iftop.html Linux安装iftop > yum install iftop -y > iftop 界面如下 ...

  10. [转帖]分析redis 大key

    http://www.lishuai.fun/2023/05/05/redis-bigkey/#/%E5%AE%89%E8%A3%85 redis-rdb-tools 是一个 python 的解析 r ...