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

最近要完成一个功能,就是把四个视频合成左右上下分布的一个视频。尝试很多方法,最终使用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/opencv4Name: 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-configprefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include/opencv4Name: 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));//.avitrack_writer.open (mergeVideoFile, cv::VideoWriter::fourcc('m', 'p', '4', 'v'), mergeVideooFps, cv::Size(mergeVideooWidth, mergeVideooHeight));//.mkvif(!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);//创建目标MatMat 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(jni环境)
上述已经说过,在linux编译的库文件为x86_64平台,我需要arm64平台。因此上述不满足我的需求。使用其他办法。在AS中集成opencv。
1、下载opencv 使用android平台的sdk包。
下载地址不变:下载地址:官网:https://opencv.org/releases/
在这里插入图片描述
在这里插入图片描述

2、AS中集成opencv库。查看文章"android studio 3.6.3 ndk开发-cpp文件中加载第三方.so库并生成新.so文件(二)"
链接:https://blog.csdn.net/zhuowalun8427/article/details/114294901 后半部分“AS中添加opencv环境”。
3、修改videotest.cpp。与linux环境的videotest.cpp文件相同,只是添加一些jni库文件等。在代码中详细指出。

#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>// 修改1:添加jni环境需要的头文件
#include <jni.h>
#include <android/log.h>// 修改2:jni 日志
#define TAG "lilitest" // 这个是自定义的LOG的标识
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__)using namespace std;using namespace cv;// 修改3:main() 方法改成接口,方便java层调用
int mergeVideo()
{// 修改4:路径改成android路径,我这里是外置U盘std::string videoFile = "/storage/udisk1/assets/video.mp4";//视频的路径std::string videoFile1 = "/storage/udisk1/assets/video.mp4";//视频的路径std::string videoFile2 = "/storage/udisk1/assets/video.mp4";//视频的路径std::string videoFile3 = "/storage/udisk1/assets/video.mp4";//视频的路径/** 打开第一个视频文件 */VideoCapture cap; //视频句柄变量cap.open(videoFile);//打开视频if(!cap.isOpened())  //判断是否打开了{// 修改5:所有打印日志改为LOGILOGI("1cap.isOpened is error");return -1;  }/** 打开第二个视频文件 */VideoCapture cap1; //视频句柄变量cap1.open(videoFile1);//打开视频if(!cap1.isOpened())  //判断是否打开了{LOGI("2cap.isOpened is error\n");return -1;  } /** 打开第三个视频文件 */VideoCapture cap2; //视频句柄变量cap2.open(videoFile2);//打开视频if(!cap2.isOpened())  //判断是否打开了{LOGI("3cap.isOpened is error\n");return -1;  } /** 打开第四个视频文件 */VideoCapture cap3; //视频句柄变量cap3.open(videoFile3);//打开视频if(!cap3.isOpened())  //判断是否打开了{LOGI("4cap.isOpened is error\n");return -1;} /** 打开第一个视频文件的帧数 */int frame_num = cap.get(cv::CAP_PROP_FRAME_COUNT);LOGI("videoFile total frame number is: %d",frame_num);/** 打开第二个视频文件的帧数 */int frame_num1 = cap1.get(cv::CAP_PROP_FRAME_COUNT);LOGI("videoFile1 total frame number is: %d",frame_num1);/** 打开第三个视频文件的帧数 */int frame_num2 = cap2.get(cv::CAP_PROP_FRAME_COUNT);LOGI("videoFile2 total frame number is: %d",frame_num2);/** 打开第四个视频文件的帧数 */int frame_num3 = cap3.get(cv::CAP_PROP_FRAME_COUNT);LOGI("videoFile3 total frame number is: %d",frame_num3);/** 打开第一个视频文件的帧率 */int fps = cap.get(cv::CAP_PROP_FPS);LOGI("videoFile fps: %d",fps);/** 打开第二个视频文件的帧率 */int fps1 = cap1.get(cv::CAP_PROP_FPS);LOGI("videoFile1 fps: %d",fps1);/** 打开第三个视频文件的帧率 */int fps2 = cap2.get(cv::CAP_PROP_FPS);LOGI("videoFile2 fps: %d",fps2);/** 打开第四个视频文件的帧率 */int fps3 = cap3.get(cv::CAP_PROP_FPS);LOGI("videoFile3 fps: %d",fps3);/** 打开第一个视频文件的宽度 */int image_width = cap.get(cv::CAP_PROP_FRAME_WIDTH);LOGI("videoFile image width is: %d ",image_width);/** 打开第二个视频文件的宽度 */int image_width1 = cap1.get(cv::CAP_PROP_FRAME_WIDTH);LOGI("videoFile1 image width is: %d ",image_width1);/** 打开第三个视频文件的宽度 */int image_width2 = cap2.get(cv::CAP_PROP_FRAME_WIDTH);LOGI("videoFile2 image width is:  %d",image_width2);/** 打开第四个视频文件的宽度 */int image_width3 = cap3.get(cv::CAP_PROP_FRAME_WIDTH);LOGI("videoFile3 image width is: %d ",image_width3);/** 打开第一个视频文件的高度 */int image_height = cap.get(cv::CAP_PROP_FRAME_HEIGHT);LOGI( "videoFile image height:%d ",image_height);/** 打开第二个视频文件的高度 */int image_height1 = cap1.get(cv::CAP_PROP_FRAME_HEIGHT);LOGI( "videoFile1 image height: %d",image_height1);/** 打开第三个视频文件的高度 */int image_height2 = cap2.get(cv::CAP_PROP_FRAME_HEIGHT);LOGI( "videoFile2 image height:%d ",image_height2);/** 打开第四个视频文件的高度 */int image_height3 = cap3.get(cv::CAP_PROP_FRAME_HEIGHT);LOGI( "videoFile3 image height: %d",image_height3);/** 打开第一个视频文件的矩阵对象的格式*/int frame_format = cap.get(cv::CAP_PROP_FORMAT);LOGI("videoFile frame format = %d",frame_format);/** 打开第二个视频文件的矩阵对象的格式 */int frame_format1 = cap1.get(cv::CAP_PROP_FORMAT);LOGI("videoFile1 frame format = %d",frame_format1);/** 打开第三个视频文件的矩阵对象的格式*/int frame_format2 = cap2.get(cv::CAP_PROP_FORMAT);LOGI("videoFile2 frame format = %d",frame_format2);/** 打开第四个视频文件的矩阵对象的格式 */int frame_format3 = cap3.get(cv::CAP_PROP_FORMAT);LOGI("videoFile3 frame format = %d",frame_format3);// 修改6:合并视屏的路径改为android路径,后缀只能为.avi/** 合并视频初始化 */std::string mergeVideooFile = "/storage/udisk1/assets/mergeVideotest30_1280_720.avi";int mergeVideooHeight = 720;int mergeVideooWidth = 1280;float mergeVideooFps = 30.0;int mergeVideooFpsFrameFormat = CV_8UC3; // CV_8UC3代表每个像素占8位cv::VideoWriter track_writer;Mat img = cv::Mat::zeros(mergeVideooWidth, mergeVideooHeight, mergeVideooFpsFrameFormat);// 修改7 对于android系统,fourcc只能是('M', 'J', 'P', 'G'),生成的视频格式只能是.avi否在报错“”track_writer.open (mergeVideooFile, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), mergeVideooFps, cv::Size(mergeVideooWidth, mergeVideooHeight),true);//.aviif(!track_writer.isOpened()){LOGI("!track_writer.isOpened(): ");assert("track writer open failed!\n");return -2;}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; //是否加载成功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); //我要转化为850*600大小的resize(imageROI, imageROIdst, imageROIdst.size());Mat imageROI1dst = Mat::zeros(mergeVideooHeight/2,mergeVideooWidth/2 , CV_8UC3); //我要转化为850*600大小的resize(imageROI1, imageROI1dst, imageROI1dst.size());Mat imageROI2dst = Mat::zeros(mergeVideooHeight/2,mergeVideooWidth/2 , CV_8UC3); //我要转化为850*600大小的resize(imageROI2, imageROI2dst, imageROI2dst.size());Mat imageROI3dst = Mat::zeros(mergeVideooHeight/2,mergeVideooWidth/2 , CV_8UC3); //我要转化为850*600大小的resize(imageROI3, imageROI3dst, imageROI3dst.size());// 视频写字// putText(imageROIdst, videoFile, Point(5, 55),FONT_HERSHEY_PLAIN,2.0,(0, 255, 255),2);//创建目标MatMat 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;}extern "C"
JNIEXPORT jint JNICALL
Java_com_htkj_testproject_jni_opencvActivity_myMergeVideo(JNIEnv *env, jobject thiz) {return mergeVideo();
}

代码中,fourcc与文件后缀错误,报错如下:
在这里插入图片描述
java调用接口省略。

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

1、下载sdk包,与上述相同。

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

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

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

相关文章

【Luniux】解决Ubuntu外接显示器不显示的问题

Luniux】解决Ubuntu外接显示器不显示的问题 文章目录 Luniux】解决Ubuntu外接显示器不显示的问题1. 检查nvidia显卡驱动是否正常2. 更新驱动3. 检查显示器是否能检测到Reference 1. 检查nvidia显卡驱动是否正常 使用命令行 nvidia-smi来检查显卡驱动是否正常&#xff0c;如果…

3、监测数据采集物联网应用开发步骤(3)

监测数据采集物联网应用开发步骤(2) 系统整体结构搭建 新建项目 输入项目名称&#xff1a;MonitorData 所谓兵马未动粮草先行&#xff0c;按下图创建好对应的模块备用&#xff1a; com.plugins 业务插件模块 com.zxy.adminlog 日志或文本文…

《C和指针》笔记12: 存储类型(自动变量、静态变量和寄存器变量)

文章目录 1. 自动变量&#xff08;auto&#xff09;1.1 自动变量的初始化 2. 静态变量&#xff08;static&#xff09;2.1 静态变量的初始化 3. 寄存器变量&#xff08;register&#xff09; 1. 自动变量&#xff08;auto&#xff09; 在代码块内部声明的变量的缺省存储类型是…

小白必看:期权行权前必须了解的问题。

期权的本质是一个买权或是卖权&#xff0c;也就是说你是权利方的话&#xff0c;你拥有以约定价格向对手方买入&#xff08;买权&#xff09;或卖出&#xff08;卖权&#xff09;一定数量标的的权利。期权行权就是从对手方买入&#xff0c;或向其卖出标的&#xff01;下文介绍小…

葡萄叶病害识别(图像连续识别和视频识别,Python代码,pyTorch框架)

葡萄叶病害识别&#xff08;图像连续识别和视频识别&#xff0c;Python代码&#xff0c;pyTorch框架&#xff09;_哔哩哔哩_bilibili 葡萄数据集 第一个文件夹为 Grape Black Measles&#xff08;葡萄黑麻疹&#xff09;病害&#xff08;3783张&#xff09; Grape Black rot葡…

C#调用barTender打印标签示例

使用的电脑需要先安装BarTender 我封装成一个类 using System; using System.Windows.Forms;namespace FT_Tools {public class SysContext{public static BarTender.Application btapp new BarTender.Application();public static BarTender.Format btFormat;public void Q…

【pytorch】Unfold和Fold的互逆操作

1. 参数定义 Unfold https://pytorch.org/docs/stable/generated/torch.nn.Unfold.html#torch.nn.Unfold Fold https://pytorch.org/docs/stable/generated/torch.nn.Fold.html#torch.nn.Fold 注意&#xff1a;参数当中的padding是在四周边补零&#xff0c;而当fold后的尺寸…

Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are required

项目场景&#xff1a; 最近因为公司业务需要在搭一个新架构&#xff0c;用的springboot3和jdk17,在整合mybatis多数据源的时候报错 &#xff08;引用的mybatisplus 和 mybatisplusjion的是最新的包-2023-08-26&#xff09; Error creating bean with name ‘XXXServiceImpl’:…

无涯教程-Android Studio函数

第1步-系统要求 您将很高兴知道您可以在以下两种操作系统之一上开始Android应用程序的开发- MicrosoftWindows10/8/7/Vista/2003(32或64位)MacOSX10.8.5或更高版本,最高10.9(小牛) GNOME或KDE桌面 第二点是,开发Android应用程序所需的所有工具都是开源的,可以从Web上下载。以…

【FPGA】verilog语法的学习与应用 —— 位操作 | 参数化设计

【FPGA】verilog语法的学习与应用 —— 位操作 | 参数化设计 学习新语法&#xff0c;争做新青年 计数器实验升级&#xff0c;让8个LED灯每个0.5s的速率循环闪烁&#xff0c;流水灯ahh好久不见~ 去年光这个就把我折磨够呛。。我肉眼可见的脱发就是从那时候开始的。。在那两个月…

代码随想录打卡—day46—【DP】— 8.29 背包END

1 139. 单词拆分 139. 单词拆分 做了很久...估计2h 一开始我的思路卡死了 看题解之后的思路的详解见注释&#xff0c; 我的写法和carl 答案在一些微小的细节上略有不同&#xff0c;我的更好理解&#xff0c;但他的解法更简单。 我写的过程中&#xff0c;需要注意下标和字符…

爬虫逆向实战(二十四)--某鸟记录中心

一、数据接口分析 主页地址&#xff1a;某鸟记录中心 1、抓包 通过抓包可以发现数据接口是front/record/search/page 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现&#xff0c;请求参数是加密的 请求头是否加密&#xff1f; 通过查…

基于 OV5640 的图像采集显示系统(DVP 接口时序逻辑设计)

文章目录 前言一、DVP 接口时序逻辑设计二、基本数据流接收三、像素位置输出四、舍弃前 N 张图像五、系统异常状态恢复控制六、完整代码展示七、仿真代码展示八、仿真波形展示前言 上一节,我们已经完成了 OV5640 初始化逻辑的介绍。接下来,将要开始完成 DVP 接口的时序设计。…

【C修炼计划】卷壹 · 初识C语言

文章目录 卷壹 初识C语言一 C语言的起源二 C语言的特性三 C语言的应用范围四 C语言程序结构五 C语言书写规范六 C语言编译器安装附 参考资料 卷壹 初识C语言 一 C语言的起源 C语言的前生是B语言&#xff08;BCPL&#xff0c;一种早期的高级语言&#xff09;。下图描…

1. 卷积原理

① 卷积核不停的在原图上进行滑动&#xff0c;对应元素相乘再相加。 ② 下图为每次滑动移动1格&#xff0c;然后再利用原图与卷积核上的数值进行计算得到缩略图矩阵的数据&#xff0c;如下图右所示。 import torch import torch.nn.functional as Finput torch.tensor([[1, 2…

华为AR路由器 典型配置案例——以太网交换

目录 Eth-Trunk 例&#xff1a;配置三层链路聚合 组网需求 操作步骤 检查配置结果 配置脚本 VLAN 举例&#xff1a;配置基于接口划分VLAN&#xff0c;实现同一VLAN内的互通&#xff08;同设备&#xff09; 组网需求 操作步骤 检查配置结果 配置脚本 举例&#xff…

C# 使用SnsSharp实现文件拖拽功能

CSDN下载地址&#xff1a;https://download.csdn.net/download/sns1991sns/88041637 gitee下载地址&#xff1a;https://gitee.com/linsns/snssharp 技术优势&#xff1a; 不仅使用简单&#xff0c;还可解决由于系统管理权限导致的文件拖拽无响应问题。 使用举例&#xff1a…

PDF制作成翻页电子书

在日常工作中&#xff0c;大部分人使用的都是PDF文档发送给客户&#xff0c;但是PDF文档通常是静态的&#xff0c;缺乏交互性和视觉吸引力。那你有没有想过把它转换成翻页的电子书呢&#xff1f; 小编将告诉你操作步骤&#xff0c;非常简单 1.搜索FLBOOK在线制作电子杂志平台 …

十二、pikachu之URL重定向

文章目录 1、URL重定向概述2、实战3、URL跳转的几种方式:3.1 META标签内跳转3.2 javascript跳转3.3 header头跳转 1、URL重定向概述 不安全的url跳转问题可能发生在一切执行了url地址跳转的地方。如果后端采用了前端传进来的&#xff08;可能是用户传参&#xff0c;或者之前预埋…

官宣|美洽AI客服 x HelpLook 达成联盟合作,AI ChatBot 解放客户运营

重磅消息 美洽AI客服和HelpLook 正式建立合作关系 随着企业扩大规模和业务增长&#xff0c;客户咨询和服务请求增加。传统人工客服难以处理大量咨询&#xff0c;而智能化的AI客服可以同时满足多个客户需求。AI客服系统建立和训练好后&#xff0c;能自动化处理客户咨询&#x…