首页 > 系统相关 >基于Luckfox Pico的opencv使用UDP协议与ubuntu传输摄像头数据-小白进阶

基于Luckfox Pico的opencv使用UDP协议与ubuntu传输摄像头数据-小白进阶

时间:2024-05-06 10:56:55浏览次数:25  
标签:Luckfox addr server opencv ubuntu sockfd include cv 进阶

使用UDP传输opencv的mat数据并显示

本教程适用于进阶的小白尝试
先说一下背景吧,正在工作的我,突然间看到淘宝上有个很漂亮的价格还不错的linux小板子,遂买下。没错,工作太无聊以至于开始摸鱼学习~
但奈何每天工作完回家就像躺着,所以板子到手都快半年了才开始研究
实现了简陋的摄像头传输,所以如果有大佬们有更优的代码请评论区讨论,必有3Q回复~
话不多说请看效果图
在这里插入图片描述

器材准备

硬件:
1.Luckfox Pico小板一个
2.Luckfox Pico配套摄像头一个
3.一个小TF卡(我用的是16G的)
软件:
1.带ubuntu的虚拟机
2.ubuntu安装opencv
3.win下的终端我用的MobaXterm
4.luckfox官方教程网页

小板子我是看了价格便宜买的,才四十,感觉linux的学习成本越来越低喽
在这里插入图片描述
摄像头五十拿下
在这里插入图片描述

基础说明

0.需要将tf卡按照官方教程烧录好
1.此教程是基于Luckfox Pico的 “优质社区分享”-----“opencv-mobile” 篇章做的延申,所以可以先将opencv-mobile篇章做完,这样可以确定摄像头到开发板到电脑的链路是通的。luckfox的opencv-mobile篇章
ubuntu
2.虚拟机中的opencv需要安装好,以便ubuntu调用显示 opencv安装教程及说明
3.还会用到利用opencv的编译 opencv的cmake最简单编译
以上四步完成后,下面的操作简直就易如反掌了

win与虚拟机网络设置

我当前的做法是将开发板连接到win电脑,然后通过虚拟机的桥接模式连接到虚拟机,做法如下

WIN连接

其实官方有说明了,不过为了方便大家我还是列出来吧
开发板本身的地址是172.32.0.93
开发板通过typec连接到电脑后电脑会自动多出一个网络连接
名称是“Remote NDIS based Internet Sharing Device”
在这里插入图片描述
将此网络的IPV4的ID改成172.32.0.100,这是为了让电脑与开发板在同一网段下可以相互访问
在这里插入图片描述
至此,便可以使用MobaXterm连接至开发板
用户名:root
密码:luckfox
在这里插入图片描述

虚拟机连接

首先打开虚拟网络编辑器
在这里插入图片描述
将桥接模式的网络设置为开发板的网络(别忘应用哦)
在这里插入图片描述
其次将虚拟机的设置指定为刚设置好的桥接
在这里插入图片描述
然后在ubuntu系统中将网络地址手动设置为172.32.0.101(其实和win下类似,不过是防止与win冲突)
在这里插入图片描述
至此网络设置完美落幕

开发板程序

直接基于官方的luckfox的opencv-mobile篇章内的代码稍作改动(这也是为什么建议先将官方的opencv例子跑通)
拓展:需要注意的是,官方的opencv精简,所以无法使用此opencv库来发送已有的图片,因为官方的opencv精简到无法读取图片哈哈哈哈

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

#include <unistd.h>   // sleep()
 

#define SERVER_IP "172.32.0.101" // 服务器IP地址,这里使用本地地址作为示例
#define SERVER_PORT 90     // 服务器端口号,根据你的需要设置

int main()
{
    cv::VideoCapture cap;
    cap.set(cv::CAP_PROP_FRAME_WIDTH, 320);
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, 240);
    cap.open(0);

    // cv::Mat images = cv::imread("123.jpg");
    // if(images.empty()){
    //     printf("oprn .jpg error!\n");
    //     return -1;
    // }

    const int w = cap.get(cv::CAP_PROP_FRAME_WIDTH);
    const int h = cap.get(cv::CAP_PROP_FRAME_HEIGHT);
    fprintf(stderr, "%d x %d\n", w, h);

    cv::Mat bgr;

        cap >> bgr;

        sleep(1);


    cap.release();


        cv::Mat out(h , w , CV_8UC3);
        bgr.copyTo(out(cv::Rect(0, 0, w, h)));

        cv::imwrite("out.jpg", out);



#if 1
    int sockfd;
    struct sockaddr_in server_addr;
    char *message = "Hello, UDP Server!"; // 要发送的消息内容
    int bytes_sent, bytes_received;
 
    // 创建UDP socket
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }
    printf("Socket created successfully.\n");
 
    // 设置服务器地址信息
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET; // 使用IPv4地址族
    server_addr.sin_port = htons(SERVER_PORT); // 设置端口号(网络字节序)
    inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr); // 设置服务器IP地址
 
      // 将图片编码为JPG格式
    std::vector<uchar> buf;
    cv::imencode(".jpg", bgr, buf);

    uint32_t size_buf = buf.size();

    // 发送数据到服务器
    bytes_sent = sendto(sockfd, &size_buf, sizeof(buf.size()), 0, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if (bytes_sent < 0) {
        perror("Sendto failed");
        exit(EXIT_FAILURE);
    }
    printf("Data sent to server successfully.\n");
 
    sleep(1);
    
    bytes_sent = sendto(sockfd, buf.data(), buf.size(), 0, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if (bytes_sent < 0) {
        perror("Sendto failed");
        exit(EXIT_FAILURE);
    }
    printf("Data sent to server successfully.\n");

    // 这里可以添加接收服务器响应的代码(使用recvfrom函数)...(略)...
    // ...处理接收到的数据...(略)...
 
    close(sockfd); // 关闭socket连接
#endif

    return 0;
}

ubuntu程序

这是我的ubuntu的程序,大概意思就是先接收图片的大小,然后再按照大小接收图片的数据。
备注:有时候接收的大小也会乱掉,大家多跑几次就通了哈哈哈,毕竟不是精装房~

先看我的代码结构,因为这也是用cmake来做的编译
在这里插入图片描述
然后是cmakelists的代码,其实套路就是 opencv的cmake最简单编译

project(test)
cmake_minimum_required(VERSION 3.5)
set(CMAKE_CXX_STANDARD 11)

SET(CMAKE_C_COMPILER "g++")
SET(CMAKE_CXX_COMPILER "g++")

#set(OpenCV_DIR "${CMAKE_CURRENT_SOURCE_DIR}/usr/lib/x86_64-linux-gnu/cmake/opencv4")
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

add_executable(test opencv.cpp)

target_link_libraries(test ${OpenCV_LIBS})

以下才是真正的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
 
#define BUFFER_SIZE (1024 * 16)
#define PORT 90
 
int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[BUFFER_SIZE];
    int received_bytes;
 
    // 创建socket
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }
 
    // 设置服务器地址结构
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 
    // 绑定socket到服务器地址
    if (bind(sockfd, (const struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
 
    printf("Waiting for data on port %d\n", PORT);
    uint32_t len = 0;
    // 接收数据
    while (1) {
        while(1)
        {
            memset(buffer, 0, 4);
            received_bytes = recvfrom(sockfd, buffer, 4, 0, NULL, NULL);
            if (received_bytes < 0) {
                perror("recvfrom failed");
                exit(EXIT_FAILURE);
            }
            if((buffer[1]<0x40)&&(buffer[1]>0x10))
            {
                if((buffer[2]==0x00)&&(buffer[3]==0x00))
                {
                    len = ((uint32_t)buffer[3]<<24)|((uint32_t)buffer[2]<<16)|((uint32_t)buffer[1]<<8)|((uint32_t)buffer[0]);
                    printf("Received length: %x\n", len);
                    break;
                }
                else
                {
                    printf("buffer 2-3 is not 0x00 ! %x %x %x %x\n",buffer[0],buffer[1],buffer[2],buffer[3]);
                }

            }
            else
            {
                printf("buffer 0-1 is not 0x20-0x25 ! %x %x %x %x\n",buffer[0],buffer[1],buffer[2],buffer[3]);
            }

        }
        memset(buffer, 0, len);
        received_bytes = recvfrom(sockfd, buffer, len, 0, NULL, NULL);
        if (received_bytes < 0) {
            perror("recvfrom failed");
            exit(EXIT_FAILURE);
        }
        printf("Received message!\n");

        cv::Mat image = cv::imdecode(cv::Mat(1, received_bytes, CV_8UC1, buffer), cv::IMREAD_COLOR);
        printf("Received image!\n");
        if (!image.empty()) {
                // 显示或处理图像
                cv::imshow("Received Image", image);
                cv::waitKey(0);
            } else {
                printf("Failed to decode image\n");
            }

    }
 
    close(sockfd);
    return 0;
}

效果

先运行虚拟机上build里的test:

sudo ./test

然后运行开发板上已经给过去的opencv-mobile-test

./opencv-mobile-test

然后就会弹出照片框喽
在这里插入图片描述

标签:Luckfox,addr,server,opencv,ubuntu,sockfd,include,cv,进阶
From: https://www.cnblogs.com/shimianxiang/p/18174547

相关文章

  • 【动画进阶】巧用 CSS/SVG 实现复杂线条光效动画
    最近,群里在讨论一个很有意思的线条动画效果,效果大致如下:简单而言,就是线条沿着不规则路径的行进动画,其中的线条动画可以理解为是特殊的光效。本文,我们将一起探索,看看在不使用JavaScript/Canvas的基础上,使用纯CSS/SVG的方式,我们可以如何大致的还原上述的线条动画效果。基于......
  • ubuntu 桥接模式无法上网解决
    ubuntu安装,根据个人的选择来配置网络信息,以下是vmare配置桥接模式时ubuntu无法上网的处理方式:1.vmare-》虚拟机-》设置,选中桥接模式(复制物理状态可以不勾选)2. vmare-》编辑-》虚拟网络编辑器,选中更改设置 2. 选中VMnet0网卡,该网卡选中电脑目前在用的网卡名称;(注意......
  • Ubuntu中CLion编译Geant4项目
    围绕自带的/examples/basic/B1展开,其他项目相关操作类似。成功安装Geant4后,首先验证B1示例能否正常运行,可以则进行下一步。安装Clion。进入B1示例,选择使用Clion打开目录中的CMakeLists.txt文件,以创建对应的项目(Project)。进入项目后,直接Run该项目可能报如下图所示错误:出现该......
  • DC-3-Joomla-Ubuntu提权
    靶机DC-3下载地址:https://www.vulnhub.com/entry/dc-32,312/翻译一下官方给出的一些信息:这个靶场与之前的不同,只有一个入口点和一个flag,并且没有任何线索。靶场只需要简单的下载,解压,打开并将其导入到VMware即可(我将其网络配置为NAT模式,保证机器与Kali在同一个网段下)一、信息收......
  • ubuntu20.04手动换源——个人向
    备份你的源,然后替换你的Linux主机上/etc/apt/source.list即可。笔者用的源如下:点击查看代码#debcdrom:[Ubuntu20.04.4LTS_FocalFossa_-Releaseamd64(20220223)]/focalmainrestricted#Seehttp://help.ubuntu.com/community/UpgradeNotesforhowtoupgra......
  • ubuntu_24.04 Noble LTS安装docker desktop启动无窗口及引擎启动失败的解决方法
    ubuntu_24.04LTS安装dockerdesktop启动无窗口及引擎启动失败的解决方法1.安装dockerdesktop后启动无窗口现象:执行sudoaptinstall./docker-desktop-4.29.0-amd64.deb成功安装dockerdesktop后,无论是在菜单里点击DockerDesktop图标还是执行systemctl--userstartdocker......
  • Ubuntu 20.04.06 修改主机名
    原因修改主机名vi/etc/hostname重启reboot......
  • 数论进阶
    数论进阶原根与阶阶若\(a,p\)互质,定义\(a\)在模\(p\)意义下的阶为最小的正整数\(t\)满足\(a^t\modp=1\)。\(a\)在模\(p\)意义下的阶记作\(ord_p(a)\),\(a^{ord_p(a)}\modp=1\)。对于整数\(k\),\(a^k\equiv1(\modp)\)当且仅当\(ord_p(a)|k\)。计算......
  • Ubuntu 20.04.6 安装教程 (VMware16)
    1.下载ubuntu进入官网地址:https://ubuntu.com/选择版本2.VMware创建虚拟机3.安装Ubuntu选择iso文件启动Ubuntu选择语言安装模式没有检测到操作系统?没关系选择地区你是Ubuntu系统的某一位用户耐心等待耐心等待之时,做件重要的事重启Ub......
  • Python进阶篇笔记
    一、面向对象1、面向过程与面向对象面向过程:把程序流程化面向对象:把程序抽象成类,类与类之间有联系2、类与对象对象就是容器,是用来存放数据和功能的,对象就是数据和功能的集合类的作用是吧对象做区分和归类,以及解决不同对象存相同数据的问题。类也是容器,也是用来存放数据和......