OpenCV入门例程:裁剪图片、模糊检测、黑屏检测

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。


        本例程运行环境为CentOS7,64位。代码很简单,三个函数分别裁剪图片、模糊检测、黑屏检测,最后是测试代码。(这个代码应该也是可以在windows上运行的,不确定是不是要经过修改)

        需要预先安装OpenCV4。

目录

一、编译参数

二、代码结构(省略的部分在后面)

三、裁剪图片

四、模糊检测

五、黑屏检测

六、测试代码

七、附加说明


一、编译参数

         在OpenCV官网下载安装:

        注意,本人所用版本没有这么新,不过应该不影响。 

        程序使用OpenCV需要头文件和库:

头文件包含目录,按照你的安装位置
-I /usr/local/include/opencv4/
链接库,这是全部,程序本身应该不需要链接这么多-lopencv_core -lopencv_imgcodecs -lopencv_highgui -lopencv_calib3d -lopencv_dnn -lopencv_features2d \-lopencv_flann -lopencv_imgproc -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching 

        如果不知道安装到哪里了,用find搜索一下就可以了。 

二、代码结构(省略的部分在后面)

#include "opencv2/opencv.hpp"
#include <opencv2/imgproc/types_c.h>
using namespace cv;//图像处理类
class CMyPic
{
private:
public://裁剪图片static bool ClipPic(char const* infile, int x, int y, int width, int heigh, char const* outfile){。。。。。。}//模糊检测static double isImageBlurry(cv::Mat& img){。。。。。}// cast 占比值,阈值为0.85,占比大于阈值认为黑屏static double detect_blackscreen(cv::Mat input_img){。。。。。。}static bool CMyPic_test(){。。。。。。}
};

        三个功能三个函数,还有一个是测试。其实四个函数都是独立的,并不需要包装起来。

三、裁剪图片

	//裁剪图片static bool ClipPic(char const* infile, int x, int y, int width, int heigh, char const* outfile){Mat pic = imread(infile);if (NULL == pic.data){thelog << "imread失败" << ende;return false;}Rect rect(x, y, width, heigh);Mat newpic = pic(rect);if (NULL == newpic.data){thelog << "剪切失败" << ende;return false;}if (!imwrite(outfile, newpic)){thelog << "imwrite失败" << ende;return false;}return true;}

        裁剪图片不在后面的测试代码中,因为这个代码一直在使用,所以也不用测试。

        功能很简单,打开输入文件,读取RECT范围到新图片,输出到outfile,文件格式OpenCV会根据文件后缀名自动处理。

        用到的几个OpenCV功能:

  • imread(文件名) 读取图片文件到Mat结构,根据文件扩展名自动识别格式
  • Mat::Mat(RECT) 剪切图片……这也太简单了
  • imwrite(文件名,Mat对象) 写文件,根据文件扩展名自动选择输出格式

四、模糊检测

	//模糊检测static double isImageBlurry(cv::Mat& img){cv::Mat matImageGray;// converting image's color space (RGB) to grayscalecv::cvtColor(img, matImageGray, CV_BGR2GRAY);cv::Mat dst, abs_dst;cv::Laplacian(matImageGray, dst, CV_16S, 3);cv::convertScaleAbs(dst, abs_dst);cv::Mat tmp_m, tmp_sd;double m = 0, sd = 0;//int threshold = 1000;cv::meanStdDev(dst, tmp_m, tmp_sd);m = tmp_m.at<double>(0, 0);sd = tmp_sd.at<double>(0, 0);return (sd * sd);}

        这个就有点复杂了,先转换成灰度,再执行拉普拉斯算子,然后……好吧,其实我也不懂。

        用到的几个OpenCV功能:

  • cvtColor 转换颜色
  • Laplacian 拉普拉斯算子
  • convertScaleAbs 取绝对值
  • meanStdDev 计算平均值和标准差

五、黑屏检测

	// cast 占比值,阈值为0.85,占比大于阈值认为黑屏static double detect_blackscreen(cv::Mat input_img){cv::Mat gray_img;cv::cvtColor(input_img, gray_img, CV_BGR2GRAY);long dark_sum = 0;for (long i = 0; i < gray_img.rows; ++i){for (long j = 0; j < gray_img.cols; ++j){if (gray_img.at<uchar>(i, j) < 20){++dark_sum;}}}return dark_sum / double(gray_img.total());}

        先转换成灰度,再计算灰度小于20的点的占比。 返回的是占比,跟阈值比较即可。

        这个算法只用到了转换颜色cvtColor。

六、测试代码

	static bool CMyPic_test(){struct dirent* drip;DIR* dp;string dirname="目录";if ((dp = opendir(dirname.c_str())) == NULL){thelog << "Error open dir " << dirname << " : " << strerror(errno) << ende;return false;}int ret = 0;while ((drip = readdir(dp)) != NULL){if (strcmp(drip->d_name, ".") == 0 || strcmp(drip->d_name, "..") == 0){continue;}string fullname;fullname = dirname + "/" + drip->d_name;//thelog<<fullname<<endi;bool isdir = IsDir(fullname.c_str());if (isdir){thelog << fullname << "是个目录" << endi;continue;}string ext = ".jpg";//任务文件扩展名int d_name_len = strlen(drip->d_name);if (0 != strcmp(ext.c_str(), drip->d_name + d_name_len - ext.size())){continue;}Mat pic = imread(fullname.c_str());if (NULL == pic.data){thelog << "imread失败" << ende;return false;}//检测模糊double Blurry = isImageBlurry(pic);if (Blurry < 1000){thelog << fullname << "模糊 " << Blurry << endi;}else{//thelog << fullname<< "不模糊" << endi;}//检测黑屏double Black = detect_blackscreen(pic);if (Black > 0.85){thelog << fullname << "黑屏 " << Black << endi;}else{//thelog << fullname << "不黑屏" << endi;}char buf[128];sprintf(buf, ".%ld.%ld.jpg", (long)Blurry, (long)(Black*100));if (!imwrite(((string)drip->d_name + buf).c_str(), pic)){thelog << "imwrite失败" << ende;return false;}}closedir(dp);thelog << dirname << " 处理完毕" << endi;return true;}

        这个测试代码读取目录下的所有文件输出判断结果。 

七、附加说明

        测试代码用到了thelog,功能就是日志输出,替换为cout,ende和endi替换为endl即可。

        操作目录的部分需要包含头文件dirent.h。IsDir的实现是这样的:

		bool IsDir(char const * strPathName){struct stat statBuf;if (stat(strPathName, &statBuf) == -1){//这里总是返回-1,不知道是什么原因cout << "stat error : " << strPathName << " " << strerror(errno) << endl;return false;}return(statBuf.st_mode & S_IFDIR);}

        这个函数似乎有BUG,没搞清怎么回事,这个代码以前是可以用的,也不知道怎么回事,不过不影响测试代码的主要目的。


(这里是文档结束)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/794175.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JS详解-函数柯里化

简介&#xff1a; 柯里化&#xff08;Currying&#xff09;是一种关于函数的高阶技术。柯里化是一种函数的转换&#xff0c;它是指将一个函数从可调用的 f(a, b, c) 转换为可调用的 f(a)(b)(c)。柯里化不会调用函数。它只是对函数进行转换。 举个例子&#xff1a; 已最简单的…

图像处理入门 3(how to get the pixel pitch / 如何获得单个像素的尺寸)

在这里一节里面&#xff0c;将记录如何获得一个相机传感器中单个像素点的尺寸&#xff0c;为了实现不同相机照片之间的匹配。 如果我们知道了相机传感器的尺寸和分辨率的大小&#xff0c;自然就可以求出单个像素的大小。 在这里插入图片描述&#xff1a; 如何获得相机传感器的…

golang设计模式图解——模板方法模式

设计模式 GoF提出的设计模式有23个&#xff0c;包括&#xff1a; &#xff08;1&#xff09;创建型(Creational)模式&#xff1a;如何创建对象&#xff1b; &#xff08;2&#xff09;结构型(Structural )模式&#xff1a;如何实现类或对象的组合&#xff1b; &#xff08;3&a…

【JavaSE】反射

Java代码的生命周期 Java代码在计算机中经历的阶段&#xff1a;Source源代码阶段、Class类对象阶段、RunTime运行时阶段。 Source源代码阶段: 这个阶段是由程序员编写生成源代码,再由Javac编译器生成class文件。 Class类对象阶段&#xff1a;由类加载器将class文件加载到JVM内…

【网站项目】少儿编程管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

备战蓝桥杯---多路归并与归并排序刷题

话不多说&#xff0c;直接看题 1. 我们考虑一行一行合并&#xff0c;一共m次&#xff0c;我们合并两个并取前n小&#xff0c;那么我们怎么取&#xff1f; 我们采用分组的思想&#xff1a; 我们选第一列的min,然后把后面那个再纳入考虑&#xff0c;用优先队列实现即可。 下面…

chatGPT4无法登录

遇到问题&#xff1a;chatgpt网站上点击登录&#xff08;log in),网站就会跳转并显示&#xff1a;unable to connect 解决方法&#xff1a;不要用亚洲节点&#xff0c;亚洲节点被全面封禁&#xff0c;在全局代理中可以换成美国的节点

synchronized到底锁住的是谁?

我们使用synchronized关键字是用来实现线程同步的&#xff0c;当多个线程同时去争抢同一个资源的时候在资源上边加一个synchronized关键字&#xff0c;能够使得线程排队去完成操作。 synchronized到底锁定的是什么资源&#xff1f; 修饰方法非静态方法 &#xff0c;锁定的是方…

《UE5_C++多人TPS完整教程》学习笔记30 ——《P31 摄像机和弹簧臂(Camera And Spring Arm)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P31 摄像机和弹簧臂&#xff08;Camera And Spring Arm&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&#xff08;…

使用git 和 github协作开发

文章目录 github浏览器汉化插件github新建仓库git安装以及ssh配置团队创建及基本命令的使用创建团队基本命令 分支管理快速切换远程仓库地址 如何使用git && github进行协作开发&#xff0c;包括git常见基础命令 github浏览器汉化插件 在刚开始使用github的时候&#…

ubuntu安装docker,并搭建vulfocus靶场

ubuntu安装docker&#xff0c;并搭建vulfocus靶场 docker是一个容器管理的软件&#xff0c;容器背后其实就是一个进程&#xff1b;类似于一个集装箱。 docker的官方下载地址&#xff1a;Install Docker Engine on Ubuntu | Docker Documentation&#xff08;可以根据自己需要的…

【文献分享】机器学习 + 分子动力学 + 第一性原理 + 热力学性质 + 微观结构

分享一篇关于机器学习 分子动力学 第一性原理 热学性质&#xff08;密度、比热容、导热率和粘度&#xff09; 微观结构的文章。 感谢论文的原作者&#xff01; 关键词&#xff1a; 1. Deep potential 2. Machine learning 3. Molecular dynamics 4. Microscopic structu…

Linux| Awk 中“next”命令奇用

简介 本文[1]介绍了在Linux中使用Awk的next命令来跳过剩余的模式和表达式&#xff0c;读取下一行输入的方法。 next命令 在 Awk 系列教程中&#xff0c;本文要讲解如何使用 next 命令。这个命令能让 Awk 跳过所有你已经设置的其他模式和表达式&#xff0c;直接读取下一行数据。…

【无标题】【Android】Android中Intent的用法总结

2.显示地图: Java代码 Uri uri Uri.parse(“geo:38.899533,-77.036476”); Intent it new Intent(Intent.Action_VIEW,uri); startActivity(it); 3.从google搜索内容 Java代码 Intent intent new Intent(); intent.setAction(Intent.ACTION_WEB_SEARCH); intent.pu…

【C++进阶】【STL】set和map的讲解及模拟实现

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;c大冒险 总有光环在陨落&#xff0c;总有新星在闪烁 一、 关联式容器 在初阶阶…

github中git clone需要username和password问题

username&#xff1a;一般指你的昵称 password&#xff1a;一般指Creating a fine-grained personal access token 这个的获取办法如下&#xff08;注意&#xff0c;在11步的时候&#xff0c;记得打开你仓库对应的一些access 权限&#xff09;&#xff1a; Note: Fine-graine…

动态规划刷题(算法竞赛、蓝桥杯)--线段(线性DP)

1、题目链接&#xff1a;P3842 [TJOI2007] 线段 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include <bits/stdc.h> using namespace std; const int N20010; int a[N][2],f[N][2]; //a[i][0]表示l[i],a[i][1]表示r[i] int dis(int a,int b){return abs(a-b); } int…

Java中的网络编程(一)

一、网络编程概述 什么是计算机网络把不同区域的计算机&#xff08;广义&#xff09;通过通信设备和线路连接&#xff0c;可以实现数据的传输和共享的系统。实现不同计算机之间的练习&#xff0c;必须有介质连接。网络编程是干什么的聊天-->聊天软件 QQjava语言是支持网络间…

从人机界面设计黄金三法则视角看 ChatGPT 的界面设计的“好”与“坏”

热门文章推荐&#xff1a; &#xff08;1&#xff09;《为什么很多人工作 3 年 却只有 1 年经验&#xff1f;》&#xff08;2&#xff09;《一文掌握大模型提示词技巧&#xff1a;从战略到战术巧》&#xff08;3&#xff09;《AI 时代&#xff0c;程序员的出路在何方&#xff1…

数组方法汇总

数组和链表类似&#xff0c;都是用双指针&#xff0c;但数组不需要额外的指针&#xff0c;可以使用索引来当作指针。&#xff08;链表的时候要注意&#xff0c;什么时候是移动的指针&#xff0c;什么时候是改变的节点&#xff09;删除有序数组中的重复项 注意&#xff0c;本题中…