基于树莓派OpenCV+OLED的无线图传系统(PS:仅作自述,勿参考)

方案选型:
1、OpenCV(C++)
2、0.96 OLED
3、串口

一,OpenCV

这里我选用是C++和Python都支持的CV依赖包,而不是只支持Python的CV包,对于长远来说,我更喜欢C++编程运行来计算机视觉程序,而不太喜欢Python (可能这并不是一件好事),至于为什么,个人偏好而已。

于是就开启了几天头疼的下载、安装、编译…

安装流程参考博客:亲测有效 [自己一遍又一遍的安装,最后找到的比较靠谱的两篇博客]
博客1:https://www.linuxidc.com/Linux/2019-08/159878.html
博客2:https://www.lijl888.com/archives/1127
踩坑点:
1、在网上查找下载安装时,尽量找时间离当下最近的,时间太过于久远就没有必要看了,树莓派安装也要跟得上时代发展。
2、树莓派一系列基础操作:换源 (换为清华镜像源,记得去官网查阅换源的方法),使能摄像头,更新…

sudo apt-get update
sudo apt-get upgrade

3、(我的)树莓派系统镜像默认没有Cmake,如果想要对CV的源代码文件进行编译的话,需要自己下载一个:

sudo apt install cmake  # 最简单的办法,但是安装的Cmake好像是旧版本的

这里我推荐是使用Cmake的新版本,可以参考博客:https://blog.csdn.net/weixin_43371047/article/details/103763918
4、make编译的时候如果出现下列错误:

~/opencv_contrib/modules/xfeatures2d/src/boostdesc.cpp:673:20: fatal error: boostdesc_bgm.i: No such file or directory

可以参考博客:https://blog.csdn.net/qq_38131812/article/details/90292703

boostdesc_bgm.i
boostdesc_bgm_bi.i
boostdesc_bgm_hd.i
boostdesc_lbgm.i
boostdesc_binboost_064.i
boostdesc_binboost_128.i
boostdesc_binboost_256.i
vgg_generated_120.i
vgg_generated_64.i
vgg_generated_80.i
vgg_generated_48.i

在自己的电脑下载好之后直接使用FileZilla远程传输到树莓派对应的文件夹,然后重新make就行。
5、输入命令,测试环境是否安装成功:

# example Test

6,(可选)安装Vscode:
参考视频教程:https://www.bilibili.com/video/av970000779/
其中下载完之后不必配置tasks.json、launch.json、c_cpp_properties.json等json文件,对于我来说,VScode就是一个文本文档,最终的编译运行由g++ 进行。
你只需要建立如下文件结构,然后使用CmakeTerminal来运行就OK,这里不提供CmakeLists.txt,因为你需要根据实际的安装路径来编写Cmake指导编译和链接,如果这一步完不成,那很有可能你无法运行C++的CV代码 :

"quadro/minimu9-ahrs" alias home
	|-build
	|-include
	|-src

7、(可选)安装CodeBlocks:

sudo apt-get install codeblocks

基础使用教程:https://blog.csdn.net/wang_shuai_ww/article/details/17225819
不过使用CodeBlocks同样需要配置OpenCV的路径。

8,运行测试代码:

# python 代码

点击运行即可。

#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<wiringPi.h>
using namespace cv;

int main(int argc,char ** argv)
{
 	VideoCapture cap(0); // 
 	if(!cap.isOpened())
  		return -1;
 	Mat frame;
 	while(true)
 	{
  		cap >> frame;
  		imshow("raw",frame);  
  		waitKey(1);
	}
 	return 0;
}

在Terminal中进入工程文件的build文件夹,输入:

# build
cmake .. && make &&  ./opencv_9_pic_blur_1

最后大公告成,可以在树莓派上编写OpenCV代码了。

二、0.96 OLED
现展示OLED接收数据的代码:

//此函数应放入while循环中不断扫描 及时处理串口接收的信息
void UART3_Driver(void)
{
	if(USART3_RX_STA & 0x8000)	//接收到了数据
	{
		ScanScreem(USART3_RX_BUF);
		//printf("uart3 len=%d",USART3_RX_STA & 0x7fff);
		USART3_RX_STA=0;
	}
}

void ScanScreem(u8 *chr)
{
	u8 x,y;
	u16 i=0;
	
	for(y=0;y<8;y++)
	{
		OLED_Set_Pos(0,y);
		for(x=0;x<128;x++)
		{
			OLED_WR_Byte(chr[i++],OLED_DATA);
		}
	}
}

三、串口
1、下载WiringPi

sudo apt-get install wiringpi # 下载
gpio -v # 查看wringpi是否下载安装成功

2、简单的串口通信 minicom
在这里插入图片描述

3、OpenCV发送图片数据到电脑串口
4、OpenCV发送图片数据到STM32单片机
注:图片的格式为Mat类,需要转化为OLED可识别的像素点数据

vector<vector<uchar>> decode(Mat pic)   //pic
{
    int i128 = 0;
    int i64 = 0;
	int resize_height = 64;
    int resize_width = 128;
    Mat src = pic;                // 将图片传入Mat容器中
    Mat dst;
    //imshow("src", src);  // 原始图像
    resize(src, dst, Size(resize_width, resize_height), (0, 0), (0, 0), INTER_LINEAR);	
 	//imshow("13", dst);	 // 处理之后的图像   
	cvtColor(dst, dst, COLOR_BGR2GRAY);
	blur(dst, dst, Size(3, 3));	
	Canny(dst, dst, 100, 100 * 2, 3);		
	imshow("dst", dst);	 // 处理之后的图像
    int w = dst.cols * dst.channels();     //可能为3通道,宽度要乘图片的通道数
    int h = dst.rows;
    vector<vector<uchar>> array(h, vector<uchar>(w));      //初始化二维vector
    for (int i = 0; i < h; i++)
    {
        uchar* inData = dst.ptr<uchar>(i);            //ptr为指向图片的行指针,参数i为行数
        for (int j = 0; j < w; j++)
        {
            array[i][j] = inData[j];
        }
    }
    return array;
} 

void dataSendToSTM32(vector<vector<uchar>>  array)
{
	int temp;
	char str[10] = "";
	vector<vector<uchar>> dataPic(8,vector<uchar>(128));
	for(int i = 0; i<8 ; i++){
		for(int j = 0; j<128 ; j++){
			temp = 0;
			for(int bit = 0; bit<8 ;bit++){
				if (array[i * 8 + bit][j] == 255)
                	temp |= 0x01 << bit;
			}
			dataPic[i][j] = temp;
			serialPutchar(fd,temp);//发送一个字符给串口
    		delayMicroseconds(0);
		}
	}
}

四,识别色块个数,发送信息给单片机

#include <string.h>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <stdio.h>
#include "wiringSerial.h"
#include "wiringPi.h"
#include <stdlib.h>
#define colorTest

using namespace cv;
using namespace std;

int fd = serialOpen("/dev/ttyAMA0",115200);//初始化串口
RNG g_rng(12345);
Mat srcPic;

int main(int argc, char* argv[])
{
    Mat Pic;
	VideoCapture capture(0); 
    float AreaByTest = 0;
    vector<vector<uchar>> arrayT;
    Mat element = getStructuringElement(MORPH_RECT,Size(15,15));  
    cv::Scalar scalarL = cv::Scalar(100,43,46);
    cv::Scalar scalarH = cv::Scalar(124,255,255);
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
    int n = 0;

    wiringPiSetup();
    while(1)
    {
        #ifndef colorTest
        cout<<"Wait~";
        cin >> n;
        switch(n){
            case 1:srcPic = imread("//home//pi//Desktop//Cpp_OpenCV//testPic//b1.jpg"); break;
            case 2:srcPic = imread("//home//pi//Desktop//Cpp_OpenCV//testPic//b2.jpg"); break;
            case 3:srcPic = imread("//home//pi//Desktop//Cpp_OpenCV//testPic//b3.jpg"); break;
            case 4:srcPic = imread("//home//pi//Desktop//Cpp_OpenCV//testPic//b4.jpg"); break;
            case 5:srcPic = imread("//home//pi//Desktop//Cpp_OpenCV//testPic//b5.jpg"); break;
            case 6:srcPic = imread("//home//pi//Desktop//Cpp_OpenCV//testPic//b6.jpg"); break;
            default:break;
        }
        cout<<"OK!"<<endl;
        imshow("Begin",srcPic);

    	cvtColor(srcPic, srcPic,COLOR_BGR2HSV);
        erode(srcPic,srcPic,element);
        inRange(srcPic,scalarL,scalarH,srcPic);
	    findContours(srcPic,contours,hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE,Point());

  	    vector<Moments> mu(contours.size());
	    for (unsigned int i = 0; i < contours.size(); i++) {
		    mu[i] = moments(contours[i], false);
	    }

	    vector<Point2f> mc(contours.size());
	    for (unsigned int i = 0; i < contours.size(); i++) {
		    mc[i] = Point2f(static_cast<float>(mu[i].m10 / mu[i].m00), static_cast<float>(mu[i].m01 / mu[i].m00));
	    }

	    Mat drawing = Mat::zeros(srcPic.size(), CV_8UC3);
	    for (unsigned int i = 0; i < contours.size(); i++) {
	    	Scalar color = Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));
		    drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
	    }
	    for (unsigned int i = 0; i < contours.size(); i++) {
		    // printf(" >通过m00计算出轮廊的[%d]的面积:(m00)= %.2f\n", i, mu[i].m00);
            AreaByTest += mu[i].m00;
		    Scalar color = Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));
	    	drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
	    }      
        printf("%d\n",(int)(AreaByTest/1050.0));
        AreaByTest = 0;
        imshow("YJ",srcPic);
        char temp = (AreaByTest/1050.0);
  		serialPutchar(fd,temp);//发送一个字符给串口      
        waitKey(0);
        #else
        capture >> Pic; 
        imshow("YJ",Pic);
        arrayT = decode(Pic);
	    dataSendToSTM32(arrayT);
        waitKey(1);
        #endif
    }   
    return 0;
}

五,发挥部分(自制微型服务器:失败)
由于树莓派是32位的Debain系统,而宝塔是64位的,为了解决这一问题:

  • 下载宝塔的历史版本
  • 修改宝塔的install.sh脚本,取消自动检测系统位数设置
wget -O install.sh http://download.bt.cn/install/install-ubuntu.sh && bash install.sh  // 报错,BT不支持32位系统
vi install.sh  //修改好之后按:wq 退出
// 删除掉 if ["$is64bit" = '32']; then 的代码段
sudo bash install.sh  // 执行安装语句

树莓派给我报了很很多错误,但是不知道会不要产生什么重大影响:
在这里插入图片描述

安装完后,宝塔会给出一个登录地址,账号和密码:
将登陆地址中括号里面的内容换为树莓派的IP地址:http://192.168.43.121:8888/
在这里插入图片描述

然后打开Chorm,输入链接,账号和密码:
然后下载宝塔需要的一些常用组件【LNMP】:
在这里插入图片描述
多半是一些和Web端打交道的工具(php)和一些存储数据的软件(MySQL)
同时还在提心吊胆,担心宝塔把树莓派的SD卡空间给榨干

df -h

在这里插入图片描述

(此图为安装之前)
安装完后,就可以输入ip地址访问到树莓派了
在这里插入图片描述
【注意:此时树莓派属于私有IP,意味着别人访问不了,要想解决这个问题,需要对树莓派进行内网穿透:使用CDN、frp内网穿透等工具则正常访问】
在这里插入图片描述在这里插入图片描述
立刻卸载宝塔:

wget http://download.bt.cn/install/bt-uninstall.sh
sh bt-uninstall.sh

然后再次打开VNC远程连接:
查阅各种方法,进不去。
第四次重装。
总结:树莓派的SD卡空间太小(我的为16GB)。

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Jetson是一款由NVIDIA开发的嵌入式计算平台,它具有高性能的GPU和专门用于AI和机器学习的硬件加速功能。而OpenCV(Open Source Computer Vision Library)是一个广泛使用的计算机视觉库,它提供了丰富的图像和视频处理功能。 当在Jetson上使用OpenCV时,有时会遇到"import cv2 Modulenotfounderror: no module named 'cv2'"的错误。这个错误通常表示系统没有找到cv2模块,导致无法引入OpenCV库。 解决此问题的方法如下: 1. 检查OpenCV是否正确安装:首先,确保已在Jetson上正确安装了OpenCV库。可以通过在终端中运行"sudo apt-get install python3-opencv"命令来安装。 2. 检查Python环境:确保在使用OpenCV的Python脚本中使用的是正确的Python解释器。有时候系统中同时存在多个Python版本,需要确保使用的是与OpenCV库相兼容的Python版本。 3. 检查库路径:打开Python交互式终端,并输入以下命令: ``` import sys print(sys.path) ``` 确保OpenCV库所在的路径在sys.path中被正确添加。 4. 检查库名称:有时候,在不同的平台上,OpenCV库的名称可能略有不同,可能是"cv2"或其他名称。请检查您的代码中是否使用了正确的库名称。 5. 重新安装OpenCV:如果以上方法都没有解决问题,可以尝试重新安装OpenCV库。可以通过重新运行安装命令,或者手动下载OpenCV源代码进行编译安装。 总之,"import cv2 Modulenotfounderror: no module named 'cv2'"错误表示系统无法找到cv2模块,导致无法引入OpenCV库。通过上述方法检查安装、Python环境、库路径等问题,可以解决此错误并成功引入cv2模块。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值