全流程机器视觉工程开发(三)任务前瞻 - 从opencv的安装编译说起,到图像增强和分割
前言
最近开始做这个裂缝识别的任务了,大大小小的问题我已经摸得差不多了,然后关于识别任务和分割任务我现在也弄的差不多了。
现在开始做正式的业务,也就是我们说的裂缝识别的任务。作为前言,先来说说场景:
现在相机返回过来的照片:
- 都是jpeg格式的照片,当然也可能是别的格式,目前主流是jpeg格式
- 大小约为11mb-14mb左右
- 图片大小为5120x5120
我们现在如果说想直接使用这个图片来进行图片识别的话,会有很多的问题。其中最主要的问题就是图片实在是过大,5120x5120的图片会导致图片不论是训练还是推理期都太长了,并且为了更好地处理图片,我们都会要求图片的训练期和推断图片都必须是比较小的,这样才有利于我们后续不论是实例分割还是目标识别任务。
目标
前言说了,我们的目标主要是两个,那就是
将现有图片分割成1280 * 1280 的小块。
为什么这么做?因为我们的图片边界刚好是5120,5120 / 4 = 1280,也就是说我们要把原先一张照片切成 4 * 4 = 16块将现有图片全部增亮
这里需要注意一点,就是在增亮图片的同时,不能让图片过曝。这里我们需要做一点特殊的处理,下文中会说。
准备
既然有了目标,那么我们就来一步步写实现。这里因为我们后续要使用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的安装编译说起,到图像增强和分割的更多相关文章
- 全球首个全流程跨平台界面开发套件,PowerUI分析
一. 首个全流程跨平台界面开发套件,PowerUI正式发布 UIPower在DirectUI的基础上,自主研发全球首个全流程跨平台界面开发套件PowerUI(PUI)正式发布,PowerU ...
- halcon机器视觉工程开发思路
参考:halcon学习笔记——机器视觉工程应用的开发思路https://www.cnblogs.com/hanzhaoxin/archive/2013/02/15/2912879.html
- 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 ...
- CentOS7+CDH5.14.0安装全流程记录,图文详解全程实测-总目录
CentOS7+CDH5.14.0安装全流程记录,图文详解全程实测-总目录: 0.Windows 10本机下载Xshell,以方便往Linux主机上上传大文件 1.CentOS7+CDH5.14.0安 ...
- Ubuntu下opencv的安装及IDEA开发配置
Ubuntu下opencv的安装及IDEA开发配置 环境配置 这篇博客主要介绍Ubuntu下opencv的安装编译,以及IDEA对opencv进行Java开发的环境配置 安装opencv 首先安装o ...
- 十分钟带你了解CANN应用开发全流程
摘要:CANN作为昇腾AI处理器的发动机,支持业界多种主流的AI框架,包括MindSpore.TensorFlow.Pytorch.Caffe等,并提供1200多个基础算子. 2021年7月8日,第四 ...
- AI全流程开发难题破解之钥
摘要:通过对ModelArts.盘古大模型.ModelBox产品技术的解读,帮助开发者更好的了解AI开发生产线. 本文分享自华为云社区<[大厂内参]第16期:华为云AI开发生产线,破解AI全流程 ...
- Halcon学习笔记——机器视觉应用工程开发思路及相机标定
机器视觉应用工程开发思路 机器视觉应用工程主要可划分为两大部分,硬件部分和软件部分. 1.硬件部分,硬件的选型至关重要,决定了后续工作是否可以正常开展,其中关键硬件部分包括:光源,相机以及镜头. 2. ...
- 基于Jenkins的开发测试全流程持续集成实践
今年一直在公司实践CI,本文将近半年来的一些实践总结一下,可能不太完善或优美,但的确初步解决了我目前所在项目组的一些痛点.当然这仅是一家之言也不够完整,后续还会深入实践和引入Kubernetes进行容 ...
- “全栈2019”Java第三章:安装开发工具IntelliJ IDEA
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
随机推荐
- AtCoder Educational DP Contest 刷题记录
写在前面 深感自己 DP 很弱的 村人B 刷了点 DP 题,题集地址戳这里. 后记:刷完后感觉自己又行了 A - Frog 1 题意 给定 \(n\) 个石头,第 i 个石头的高度为 \(h_i\). ...
- debian更新openssh 9.6
先更新一下,然后安装libssl-dev zlib1g-dev依赖文件 apt update apt install build-essential apt-get install -y libssl ...
- 制作PE工具箱
事前准备: 能上网的电脑 x1 台 大于8G的U盘 x一个(如果需要储存安装镜像的话,如果不需要的话大于1G即可) 一.下载PE工具箱 推荐使用WEPE工具箱,无广告无推广.不推荐老X桃,大X菜,大X ...
- C#格式化输入数据为货币格式
private void btn_Get_Click(object sender, EventArgs e) { double P_dbl_value;//定义double类型变量 if (doubl ...
- 万字血书Vue—Vue的核心概念
MVVM M:模型(Model):data V:视图(View):模板 VM:视图模型(ViewModel):Vue实例对象 Vue收到了MVVM模型的启发,MVVM是vue实现数据驱动视图和双向数据 ...
- Memory Bist
SRAMC主要是对SRAM进行控制 对于SRAM的逻辑,根据地址将数据存储到SRAM中,然后根据地址将SRAM中的数据读取出来 如何测试Memory,生产工艺原因造成的问题,采用DFT或者Bist测试 ...
- SQLServer命令行备份数据库
SQLServer命令行备份数据库 背景 SQLServer on linux 想设置计划任务自动备份数据库 感觉sqlcmd应该是最简单快捷的方式了 所以进行一下处理. 安装必备软件 sudo cu ...
- Oracle 高低水位线的学习
Oracle 高低水位线的学习 背景 最近产品的一些脚本会大量的给一些流程表里面插入数据 因为只是一个流程相关没有时序查询的需求 所以数据量挺大, 但是按照石时间戳删除非常麻烦. 自己执行过多次del ...
- [转帖]linux之iftop命令
https://rumenz.com/rumenbiji/linux-iftop.html Linux安装iftop > yum install iftop -y > iftop 界面如下 ...
- [转帖]分析redis 大key
http://www.lishuai.fun/2023/05/05/redis-bigkey/#/%E5%AE%89%E8%A3%85 redis-rdb-tools 是一个 python 的解析 r ...