目录
背景
这篇文章主要针对前面yolov8系列进行编写的,旨在解决使用python脚本使用opencv无法打开摄像头进行检测的问题,注意这些部署的环境都是安装在虚拟环境中的,千万不要忘记activate你的虚拟环境
1. 安装pycuda
安装pycuda之前,先安装一个projects
pip3 install projects
在pucuda官网中可以找到你想要的版本
但我使用的是2022.1版本的pycuda
2022.1版本https://pypi.org/project/pycuda/2022.1/#files下载网页中的压缩包,然后传到jetson nano上
接下来就是使用压缩包中的源代码进行安装
tar zxvf pycuda-2022.1.tar.gz
cd pycuda-2022.1/
python3 configure.py --cuda-root=/usr/local/cuda-10.2
sudo python3 setup.py install
等待安装完成后,使用以下代码进行验证
import numpy as np
import pycuda.autoinit
import pycuda.driver as cuda
from pycuda.compiler import SourceModule
mod = SourceModule("""
#define BLOCK_SIZE 16
typedef struct {
int width;
int height;
int stride;
int __padding; //为了和64位的elements指针对齐
float* elements;
} Matrix;
// 读取矩阵元素
__device__ float GetElement(const Matrix A, int row, int col)
{
return A.elements[row * A.stride + col];
}
// 赋值矩阵元素
__device__ void SetElement(Matrix A, int row, int col, float value)
{
A.elements[row * A.stride + col] = value;
}
// 获取 16x16 的子矩阵
__device__ Matrix GetSubMatrix(Matrix A, int row, int col)
{
Matrix Asub;
Asub.width = BLOCK_SIZE;
Asub.height = BLOCK_SIZE;
Asub.stride = A.stride;
Asub.elements = &A.elements[A.stride * BLOCK_SIZE * row + BLOCK_SIZE * col];
return Asub;
}
__global__ void matrix_mul(Matrix *A, Matrix *B, Matrix *C)
{
int blockRow = blockIdx.y;
int blockCol = blockIdx.x;
int row = threadIdx.y;
int col = threadIdx.x;
Matrix Csub = GetSubMatrix(*C, blockRow, blockCol);
// 每个线程通过累加Cvalue计算Csub的一个值
float Cvalue = 0;
// 为了计算Csub遍历所有需要的Asub和Bsub
for (int m = 0; m < (A->width / BLOCK_SIZE); ++m)
{
Matrix Asub = GetSubMatrix(*A, blockRow, m);
Matrix Bsub = GetSubMatrix(*B, m, blockCol);
__shared__ float As[BLOCK_SIZE][BLOCK_SIZE];
__shared__ float Bs[BLOCK_SIZE][BLOCK_SIZE];
As[row][col] = GetElement(Asub, row, col);
Bs[row][col] = GetElement(Bsub, row, col);
__syncthreads();
for (int e = 0; e < BLOCK_SIZE; ++e)
Cvalue += As[row][e] * Bs[e][col];
__syncthreads();
}
SetElement(Csub, row, col, Cvalue);
}
""")
class MatrixStruct(object):
def __init__(self, array):
self._cptr = None
self.shape, self.dtype = array.shape, array.dtype
self.width = np.int32(self.shape[1])
self.height = np.int32(self.shape[0])
self.stride = self.width
self.elements = cuda.to_device(array) # 分配内存并拷贝数组数据至device,返回其地址
def send_to_gpu(self):
self._cptr = cuda.mem_alloc(self.nbytes()) # 分配一个C结构体所占的内存
cuda.memcpy_htod(int(self._cptr), self.width.tobytes()) # 拷贝数据至device,下同
cuda.memcpy_htod(int(self._cptr)+4, self.height.tobytes())
cuda.memcpy_htod(int(self._cptr)+8, self.stride.tobytes())
cuda.memcpy_htod(int(self._cptr)+16, np.intp(int(self.elements)).tobytes())
def get_from_gpu(self):
return cuda.from_device(self.elements, self.shape, self.dtype) # 从device取回数组数据
def nbytes(self):
return self.width.nbytes * 4 + np.intp(0).nbytes
a = np.random.randn(400,400).astype(np.float32)
b = np.random.randn(400,400).astype(np.float32)
c = np.zeros_like(a)
A = MatrixStruct(a)
B = MatrixStruct(b)
C = MatrixStruct(c)
A.send_to_gpu()
B.send_to_gpu()
C.send_to_gpu()
matrix_mul = mod.get_function("matrix_mul")
matrix_mul(A._cptr, B._cptr, C._cptr, block=(16,16,1), grid=(25,25))
result = C.get_from_gpu()
print(np.dot(a,b))
print(result)
出现如下结果即安装成功
2. 重装opencv
使用摄像头主要是通过opencv打开摄像头,如果你反复测试还是无法打开摄像头 ,可能就需要重装opencv了,但这个是没有办法的事情,虽然每次编译opencv都会很耗时间
这次在重装opencv之前,除了要安装原先教程中需要安装的依赖之外,还需要多安装几个依赖,代码如下
sudo apt-get install libgtk2.0-dev pkg-config
千万记得你要将opencv安装在什么环境中,不然你后面重装opencv等待的时间就白费了
将这些依赖都准备好后,就可以重新开始安装opencv了
等待完成后,就可以正常在虚拟环境中使用opencv打开摄像头了