opencv的使用(Ubuntu linux环境,AS jni,AS java)

news2025/1/18 3:20:47

最近要完成一个功能,就是把四个视频合成左右上下分布的一个视频。尝试很多方法,最终使用opencv来实现该功能。(通过opencv实现的视频好像没有声音。)研究的步骤,首先在Ubuntu环境测试,该功能是否实现。然后再将生成的库文件放到AS中,使用jni的方法调用,或者将源码放到AS中利用jni技术。在实现过程中遇到很多问题,下面记录。
一、在ubuntu linux环境使用opencv。
1、下载opencv安装包。
下载地址:官网:https://opencv.org/releases/

在这里插入图片描述

git地址:https://github.com/opencv/opencv/releases
在这里插入图片描述
2、将下载的安装包放到虚拟机根目录(新建software目录)。
在这里插入图片描述

3、安装包解压缩。

  unzip opencv-4.8.0.zip 

4、下载相关软件。
进入 opencv-4.8.0 文件夹。
1)更新软件

sudo apt-get update

在这里插入图片描述
2)安装cmake

sudo apt-get install cmake

在这里插入图片描述
3) 安装依赖库

sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev libavformat-dev libjpeg.dev libtiff5.dev libswscale-dev libjasper-dev

在这里插入图片描述
4)在 opencv-4.8.0 文件夹下新建build文件夹。

 mkdir build

在这里插入图片描述

5)进入build文件夹,使用命令修改参数

 sudo cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local ..

在这里插入图片描述

6)使用make编译

sudo make

在这里插入图片描述
在这里插入图片描述

7)安装

sudo make install

在这里插入图片描述
8)配置环境

sudo gedit /etc/ld.so.conf.d/opencv.conf 

在新建的文档中添加:

/usr/local/lib
sudo ldconfig

配置路径生效。
在这里插入图片描述
在这里插入图片描述
9)配置bash

sudo gedit /etc/bash.bashrc 

在最末尾添加

PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig  
export PKG_CONFIG_PATH 

执行该步骤时,发现/usr/local/lib/路径下没有pkgconfig文件夹。并且执行命令

pkg-config --cflags openc

报一下错误。
在这里插入图片描述
解决:首先创建opencv.pc文件,这里要注意它的路径信息:

cd /usr/local/lib
sudo mkdir pkgconfig
cd pkgconfig
sudo touch opencv.pc

然后在opencv.pc中添加以下信息,注意这些信息需要与自己安装opencv时的库路径对应:(一下是我自己的内容)


prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include/opencv4

Name: OpenCV
Description: Open Source Computer Vision Library
Version: 4.8.0
Libs: -L${exec_prefix}/lib -lopencv_highgui -lopencv_shape -lopencv_objdetect -lopencv_ml -lopencv_superres -lopencv_dnn -lopencv_stitching -lopencv_videostab -lopencv_calib3d -lopencv_videoio -lopencv_imgcodecs -lopencv_features2d -lopencv_video -lopencv_photo -lopencv_imgproc -lopencv_flann -lopencv_core
Libs.private: -ldl -lm -lpthread -lrt
Cflags: -I${includedir}

保存退出,添加环境:

export  PKG_CONFIG_PATH=/usr/local/lib/pkgconfig

执行.cpp编译命令:

 g++ videotest.cpp -o videotest `pkg-config --cflags --libs opencv`

报错:
在这里插入图片描述
再执行编译命令:

g++ videotest.cpp -o videotest `pkg-config --cflags --libs opencv` -std=gnu++11

报错:
在这里插入图片描述
查看/usr/local/lib/lib文件下没有libopencv_shape.so等这三个库,再次打开/usr/local/lib/pkgconfig/opencv.pc文件,将-lopencv_shape 等三个路径删除掉。保存退出。执行命令:

g++ videotest.cpp -o videotest `pkg-config --cflags --libs opencv` -std=gnu++11

编译成功。
在这里插入图片描述
最后的opencv.pc文件:

# Package Information for pkg-config

prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include/opencv4

Name: OpenCV
Description: Open Source Computer Vision Library
Version: 4.8.0
Libs: -L${exec_prefix}/lib -lopencv_highgui -lopencv_objdetect -lopencv_ml -lopencv_dnn -lopencv_stitching -lopencv_calib3d -lopencv_videoio -lopencv_imgcodecs -lopencv_features2d -lopencv_video -lopencv_photo -lopencv_imgproc -lopencv_flann -lopencv_core
Libs.private: -ldl -lm -lpthread -lrt
Cflags: -I${includedir}

注意:1、该opencv源码编译的对应so库文件只是linux系统平台文件(我的是x86_64),如果想将该库编译为其他平台,例如arm64需要交叉编译。(我没整明白)
注意:2、上述配置bash后,使用以下命令使得配置文件生效。若没有生效,重启电脑试试。(如果没有生效,执行 编译生成的可执行文件,报错 找不到opencv库)

source /etc/bash.bashrc  
sudo updatedb

注意:3 我这里编译的是opencv4.8.0版本,编译过程中使用python3.x版本,opencv.pc需要自己创建。链接http://www.taodudu.cc/news/show-3639538.html?action=onClick#google_vignette 编译的opencv3.4.1版本,使用python2.x版本,opencv.pc自动生成。按照链接中配置,就可以成功编译安装opencv。

最后是测试代码,功能将代码中的video.mp4合成上下左右分布的一个视频。生成视频为mergevideo.avi 或mergevideo.mkv

#include <iostream>
#include <opencv2/opencv.hpp>
#include <unistd.h>
#include <error.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <pthread.h>
#include <linux/videodev2.h>
#include <sys/mman.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <iomanip>
#include <string>

using namespace std;
using namespace cv;
int main(int argc, char ** argv)
{
    std::string videoFile = "video.mp4";//视频的路径
    std::string videoFile1 = "video.mp4";//视频的路径
    std::string videoFile2 = "video.mp4";//视频的路径
    std::string videoFile3 = "video.mp4";//视频的路径

    /** 打开第一个视频文件 */
    VideoCapture cap; //视频句柄变量
    cap.open(videoFile);//打开视频
    if(!cap.isOpened())  //判断是否打开了
    {  
        printf("1cap.isOpened is error\n");
        return -1;  
    } 
    
    /** 打开第二个视频文件 */
    VideoCapture cap1; //视频句柄变量
    cap1.open(videoFile1);//打开视频
    if(!cap1.isOpened())  //判断是否打开了
    {  
        printf("2cap.isOpened is error\n");
        return -1;  
    } 
    
    /** 打开第三个视频文件 */
    VideoCapture cap2; //视频句柄变量
    cap2.open(videoFile2);//打开视频
    if(!cap2.isOpened())  //判断是否打开了
    {  
        printf("3cap.isOpened is error\n");
        return -1;  
    } 

    /** 打开第四个视频文件 */
    VideoCapture cap3; //视频句柄变量
    cap3.open(videoFile3);//打开视频
    if(!cap3.isOpened())  //判断是否打开了
    {  
        printf("4cap.isOpened is error\n");
        return -1;  
    } 


    /** 打开第一个视频文件的帧数 */
    int frame_num = cap.get(cv::CAP_PROP_FRAME_COUNT);
	std::cout << "videoFile total frame number is: " << frame_num << std::endl;
	
	/** 打开第二个视频文件的帧数 */
	int frame_num1 = cap1.get(cv::CAP_PROP_FRAME_COUNT);
	std::cout << "videoFile1 total frame number is: " << frame_num1 << std::endl;

    /** 打开第三个视频文件的帧数 */
    int frame_num2 = cap2.get(cv::CAP_PROP_FRAME_COUNT);
	std::cout << "videoFile2 total frame number is: " << frame_num2 << std::endl;

	/** 打开第四个视频文件的帧数 */
	int frame_num3 = cap3.get(cv::CAP_PROP_FRAME_COUNT);
	std::cout << "videoFile3 total frame number is: " << frame_num3 << std::endl;

	/** 打开第一个视频文件的帧率 */
    int fps = cap.get(cv::CAP_PROP_FPS);
	std::cout << "videoFile fps: " << fps << std::endl;

	/** 打开第二个视频文件的帧率 */
	int fps1 = cap1.get(cv::CAP_PROP_FPS);
	std::cout << "videoFile1 fps1: " << fps1 << std::endl;

    /** 打开第三个视频文件的帧率 */
    int fps2 = cap2.get(cv::CAP_PROP_FPS);
	std::cout << "videoFile fps2: " << fps2 << std::endl;

	/** 打开第四个视频文件的帧率 */
	int fps3 = cap3.get(cv::CAP_PROP_FPS);
	std::cout << "videoFile1 fps3: " << fps3 << std::endl;

	 /** 打开第一个视频文件的宽度 */
    int image_width = cap.get(cv::CAP_PROP_FRAME_WIDTH);
	std::cout << "videoFile image width is: " << image_width << std::endl;

	/** 打开第二个视频文件的宽度 */
	int image_width1 = cap1.get(cv::CAP_PROP_FRAME_WIDTH);
	std::cout << "videoFile1 image width is: " << image_width1 << std::endl;

    /** 打开第三个视频文件的宽度 */
    int image_width2 = cap2.get(cv::CAP_PROP_FRAME_WIDTH);
	std::cout << "videoFile2 image width is: " << image_width2 << std::endl;

	/** 打开第四个视频文件的宽度 */
	int image_width3 = cap3.get(cv::CAP_PROP_FRAME_WIDTH);
	std::cout << "videoFile3 image width is: " << image_width3 << std::endl;

	/** 打开第一个视频文件的高度 */
    int image_height = cap.get(cv::CAP_PROP_FRAME_HEIGHT);
	std::cout << "videoFile image height: " << image_height << std::endl;

	/** 打开第二个视频文件的高度 */
	int image_height1 = cap1.get(cv::CAP_PROP_FRAME_HEIGHT);
	std::cout << "videoFile1 image height: " << image_height1 << std::endl;

    /** 打开第三个视频文件的高度 */
    int image_height2 = cap2.get(cv::CAP_PROP_FRAME_HEIGHT);
	std::cout << "videoFile2 image height: " << image_height2 << std::endl;

	/** 打开第四个视频文件的高度 */
	int image_height3 = cap3.get(cv::CAP_PROP_FRAME_HEIGHT);
	std::cout << "videoFile3 image height: " << image_height3 << std::endl;

    /** 打开第一个视频文件的矩阵对象的格式*/
     int frame_format = cap.get(cv::CAP_PROP_FORMAT);
	std::cout << "videoFile frame format: " << frame_format << std::endl;

	/** 打开第二个视频文件的矩阵对象的格式 */
	int frame_format1 = cap1.get(cv::CAP_PROP_FORMAT);
	std::cout << "videoFile1 frame format: " << frame_format1 << std::endl;

    /** 打开第三个视频文件的矩阵对象的格式*/
     int frame_format2 = cap2.get(cv::CAP_PROP_FORMAT);
	std::cout << "videoFile2 frame format: " << frame_format2 << std::endl;

	/** 打开第四个视频文件的矩阵对象的格式 */
	int frame_format3 = cap3.get(cv::CAP_PROP_FORMAT);
	std::cout << "videoFile3 frame format: " << frame_format3 << std::endl;

	/** 合并视频初始化 */
	//std::string mergeVideoFile = "mergeVideo.avi";
    std::string mergeVideoFile = "mergeVideo.mkv";
    VideooHeight = 720;
	int mergeVideooWidth = 1280;
	float mergeVideooFps = 10.0;
	int mergeVideooFpsFrameFormat = CV_8UC3; // CV_8UC3代表每个像素占8位
	
	cv::VideoWriter track_writer;
	
    Mat img = cv::Mat::zeros(mergeVideooWidth, mergeVideooHeight, mergeVideooFpsFrameFormat);
    
    //track_writer.open (mergeVideoFile, cv::VideoWriter::fourcc('m', 'p', '4', '2'), mergeVideooFps,       cv::Size(mergeVideooWidth, mergeVideooHeight));//.avi
    
   track_writer.open (mergeVideoFile, cv::VideoWriter::fourcc('m', 'p', '4', 'v'), mergeVideooFps, cv::Size(mergeVideooWidth, mergeVideooHeight));//.mkv
   
    if(!track_writer.isOpened())
    {
       std::cout << "!track_writer.isOpened(): " << std::endl;

        assert("track writer open failed!\n");
    }
    
    Mat frame; 
    Mat frame1;
    Mat frame2; 
    Mat frame3;
    while(1)
    {
        cap.read(frame);//从第一个视频获取一帧图片
        cap1.read(frame1);//从第二个视频获取一帧图片
        cap2.read(frame2);//从第三个视频获取一帧图片
        cap3.read(frame3);//从第四个视频获取一帧图片
        
        if(frame.empty()) break; //是否加载成功
        if(frame1.empty()) break; //是否加载成功
        if(frame2.empty()) break; //是否加载成功
        if(frame3.empty()) break; //是否加载成功

        // 设定ROI区域:截取一部分进行合并
        Mat imageROI= frame(Rect(0,0,frame.cols,frame.rows)); // Rect(左上角横坐标,左上角纵坐标,宽度,高度)
        Mat imageROI1= frame1(Rect(0,0,frame1.cols,frame1.rows));
        Mat imageROI2= frame2(Rect(0,0,frame2.cols,frame2.rows));
        Mat imageROI3= frame3(Rect(0,0,frame3.cols,frame3.rows));

        // 大小转换
        Mat imageROIdst = Mat::zeros(mergeVideooHeight/2,mergeVideooWidth/2 , CV_8UC3); 
        resize(imageROI, imageROIdst, imageROIdst.size());
        
        Mat imageROI1dst = Mat::zeros(mergeVideooHeight/2,mergeVideooWidth/2 , CV_8UC3); 
        resize(imageROI1, imageROI1dst, imageROI1dst.size());
        
        Mat imageROI2dst = Mat::zeros(mergeVideooHeight/2,mergeVideooWidth/2 , CV_8UC3); 
        resize(imageROI2, imageROI2dst, imageROI2dst.size());

        Mat imageROI3dst = Mat::zeros(mergeVideooHeight/2,mergeVideooWidth/2 , CV_8UC3); 
        resize(imageROI3, imageROI3dst, imageROI3dst.size());

        // 视频写字
        // putText(imageROIdst, videoFile, Point(5, 55),FONT_HERSHEY_PLAIN,2.0,(0, 255, 255),2);

        //创建目标Mat
        Mat des;
        des.create(mergeVideooHeight,mergeVideooWidth, imageROI1dst.type()); // Mat.create(高,宽,像素编码类型这里是CV_8UC3)
        
        // 视频帧合并
        Mat r1 = des(Rect(0, 0, mergeVideooWidth/2, mergeVideooHeight/2));
        imageROI1dst.copyTo(r1);
        
        Mat r = des(Rect(mergeVideooWidth/2, 0, mergeVideooWidth/2, mergeVideooHeight/2));
        imageROIdst.copyTo(r);

        Mat r2 = des(Rect(0, mergeVideooHeight/2, mergeVideooWidth/2, mergeVideooHeight/2));
        imageROI2dst.copyTo(r2);

        Mat r3 = des(Rect(mergeVideooWidth/2, mergeVideooHeight/2, mergeVideooWidth/2, mergeVideooHeight/2));
        imageROI3dst.copyTo(r3);
        
        // 格式化要保存的视频帧
        cv::resize(des, img , cv::Size(mergeVideooWidth, mergeVideooHeight));

        // 保存视频
        track_writer.write(img);
    }
    cap.release();//释放视频句柄
    cap1.release();//释放视频句柄
    cap2.release();//释放视频句柄
    cap3.release();//释放视频句柄

    track_writer.release();
    return 0;
}

编译指令:

g++ videotest.cpp -o videotest `pkg-config --cflags --libs opencv` -std=gnu++11

执行指令:

./videotest

路径:
在这里插入图片描述
运行结果:
在这里插入图片描述

二、AS 中集成opencv(java环境)

三、AS中集成opencv(jni环境)

四、AS中集成opencv(java + jni环境)

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

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

相关文章

13.搬砖

目录 题目 Description Input Output 思路&#xff08;归并排序&#xff09; 具体步骤如下 C整体代码&#xff08;含详细注释&#xff09; 归并排序总结 核心步骤 代码模板 题目 Description 小张在暑假时间来到工地搬砖挣钱。包工头交给他一项艰巨的任务&#xff0…

Mavan进阶之父子模块(继承)

文章目录 Mavan 父子模块&#xff08;继承&#xff09;1. 父项目2. 子项目3. 父子项目的使用 Mavan 父子模块&#xff08;继承&#xff09; 「继承」是 Maven 中很强大的一种功能&#xff0c;继承可以使得子 pom 可以获得 parent 中的各项配置&#xff0c;可以对子 pom 进行统…

深度学习之反卷积

具体推理可以参考https://blog.csdn.net/zhsmkxy/article/details/107073350

uniapp微信小程序使用stomp.js实现STOMP传输协议的实时聊天

简介&#xff1a; 原生微信小程序中使用 本来使用websocket&#xff0c;后端同事使用了stomp协议&#xff0c;导致前端也需要对应修改。 如何使用 1.yarn add stompjs 2.版本 “stompjs”: “^2.3.3” 3.在static/js中新建stomp.js和websocket.js&#xff0c;然后在需要使用…

一文讲透超宽带(UWB)前世今生

►►►UWB大火与巨头入局 传闻已久的蔚来手机可能即将要发布了。据工信部官网显示&#xff1a;申请单位为蔚来移动科技有限公司、型号为N2301的手机已正式完成入网。相关认证信息显示&#xff0c;N2301支持UWB&#xff0c;可以被用作蔚来汽车的数字钥匙。 图 1 蔚来手机概念图 …

第十四课 定语从句

文章目录 前言 所有定语从句的连接词是没有意思的一、定语从句的定义和结构二、关系代词引导的定语从句1、whowho谓语&#xff08;宾语&#xff09;状语who系动词表语状语who助动词及物动词的过去分词 2、whomwhom主语及物动词&#xff08;状语&#xff09;whom主语谓语to及物动…

2023京东咖啡机行业数据分析(京东数据分析平台)

如今咖啡的渗透率越来越高&#xff0c;养成咖啡饮用习惯的消费者越来越多&#xff0c;尤其是一二线城市。同时&#xff0c;随着人们收入水平的提高&#xff0c;精致生活理念使人们对咖啡的态度从提神需求逐渐转变为社交需求&#xff0c;国内咖啡机市场的发展空间也逐步增大。 …

Oracle 本地客户端连接远程 Oracle 服务端并使用 c# 连接测试

这里写自定义目录标题 前言Oracle 客户端安装先决条件下载 Oracle 客户端Oracle 客户端环境变量配置 PL/SQLPL/SQL 下载PL/SQL 配置 配置远程连接tnsnames.ora 文件配置 使用 PL/SQL 连接远程数据库使用 C# 远程访问 Oracle 数据库结语 前言 最近有一个需要使用本地的 Oracle …

java内存分区

按照垃圾收集&#xff0c;将 Java 堆划分为**新生代 &#xff08;Young Generation&#xff09;和老年代&#xff08;Old Generation&#xff09;**两个区域&#xff0c; 新生代存放存活时间短的对象&#xff0c;而每次回收后存活的少量对象&#xff0c;将会逐步晋升到老年代中…

idea 创建mybatis xml文件时找不到

1、File >Settings 如图 &#xff1a; 2、添加模板&#xff1a;如下图 3、添加xml模板 如下图&#xff1a; 模板内容&#xff1a; <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//E…

微信小程序使用stomp.js实现STOMP传输协议的实时聊天

简介&#xff1a; uniapp开发的小程序中使用 本来使用websocket&#xff0c;后端同事使用了stomp协议&#xff0c;导致前端也需要对应修改。 如何使用 在static/js中新建stomp.js和websocket.js&#xff0c;然后在需要使用的页面引入监听代码发送代码即可 代码如下&#x…

燃气管网监测系统,提升城市燃气安全防控能力

燃气是我们日常生活中不可或缺的能源&#xff0c;但其具有易燃易爆特性&#xff0c;燃气安全使用、泄漏监测尤为重要。当前全国燃气安全事故仍呈现多发频发态势&#xff0c;从公共安全的视角来看&#xff0c;燃气已成为城市安全的重大隐忧&#xff01;因此&#xff0c;建立一个…

Linux 终端命令行 产品介绍

Linux命令手册内置570多个Linux 命令&#xff0c;内容包含 Linux 命令手册。 【软件功能】&#xff1a; 文件传输 bye、ftp、ftpcount、ftpshut、ftpwho、ncftp、tftp、uucico、uucp、uupick、uuto、scp备份压缩 ar、bunzip2、bzip2、bzip2recover、compress、cpio、dump、gun…

计算机毕设 基于深度学习的植物识别算法 - cnn opencv python

文章目录 0 前言1 课题背景2 具体实现3 数据收集和处理3 MobileNetV2网络4 损失函数softmax 交叉熵4.1 softmax函数4.2 交叉熵损失函数 5 优化器SGD6 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&a…

跨境电商面临的法律与合规问题

跨境电商在全球范围内取得了飞速的发展&#xff0c;但这一领域也伴随着复杂的法律与合规问题&#xff0c;涉及国际法律、知识产权、税务、隐私等多个方面。在跨境电商中&#xff0c;合法合规的经营不仅有助于企业长期发展&#xff0c;还能增强消费者信任&#xff0c;提升市场竞…

使用docker、docker-compose部署微服务

使用docker、docker-compose部署微服务 一、使用docker部署1、准备2、上传jar包3、编写dockerfile文件3、构建镜像和容器 二、使用docker-compose部署1、准备服务的jar包和dockerfile文件2、编写docker-compose.yml文件3、docker-compose常用命令&#xff08;1&#xff09;、前…

地下水质分析积分球

我国的河流水资源相当丰富&#xff0c;河川径流总量历年来位居世界第三&#xff0c;年均达到了27000亿m。但经济快速发展的同时对河流水资源产生了一定的负面影响&#xff0c;河流水质污染和富营养化的现象偶有发生&#xff0c;在对我国七大水系216条河流503个主要断面进行监测…

冠达管理:什么是k线怎样看k线图?

K线图是一种股票商场常用的价格图表&#xff0c;它显现了一段时刻内股票开盘价、收盘价、最高价和最低价等信息。K线起源于日本&#xff0c;在上世纪90年代被引进到全球股市中。跟着股市的开展&#xff0c;K线图已经成为股票商场数据剖析中常用的工具&#xff0c;因此了解K线图…

一文速学-让神经网络不再神秘,一天速学神经网络基础-前向传播(三)

前言 思索了很久到底要不要出深度学习内容&#xff0c;毕竟在数学建模专栏里边的机器学习内容还有一大半算法没有更新&#xff0c;很多坑都没有填满&#xff0c;而且现在深度学习的文章和学习课程都十分的多&#xff0c;我考虑了很久决定还是得出神经网络系列文章&#xff0c;…

C语言这么没用??

今日话题&#xff0c;C语言真的这么不堪吗&#xff1f;最近我兄弟向我倾诉&#xff0c;他在几天前受到老板的责骂&#xff0c;原因是他只懂C语言编程&#xff0c;无法达到老板的期望。其实不是C语言不堪&#xff0c;而是嵌入式领域复杂性多种多样&#xff0c;需要灵活的解决方案…