图像处理——连接IP摄像头上传到服务器实现目标识别

本文介绍了一个项目,它涉及使用OpenCV连接和获取大华IP摄像头的图像,然后通过Python的requests库上传到基于flask的服务器进行yolov5目标识别。服务器接收到base64编码的图像后,解码并使用模型进行处理,结果再通过socket返回给本地。讨论了实现过程中的关键步骤,包括图像获取、上传、服务器处理和结果接收,以及性能优化的考虑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

1.项目的需求是,本地连接IP摄像头,然后把图像上传到图像处理服务器器进行处理,得到的结果返回本地。

2.IP摄像头使用的是大华的摄像头,目标识别用的yolov5的模型,服务器用的是flask,实现语言是python。

3.在实现过程中,需要先进行IP摄像头的连接和图像的获取。可以使用OpenCV库来实现这一步骤。通过OpenCV库中的VideoCapture函数,可以连接到IP摄像头并获取图像。

4.获取到图像后,需要将其上传到图像处理服务器进行处理。可以使用Python中的requests库来实现图像上传功能。通过requests库中的post函数,可以将图像上传到服务器。

5.在服务器端,需要使用flask框架来实现图像处理功能。可以使用yolov5模型来进行目标识别。通过flask框架中的路由功能,可以将上传的图像进行处理,并将处理结果返回给本地。

6.最后,在本地端,需要使用Python中的socket库来实现图像结果的接收。通过socket库中的recv函数,可以接收到服务器返回的图像处理结果。

7.需要注意的是,在实现过程中,需要考虑到图像处理的时间和网络传输的延迟。可以通过优化算法和网络传输方式来提高系统的性能和响应速度。
 

一.连接摄像头

连接IP摄像头并以base64的方式上传到服务器是一种常见的操作,可以实现将摄像头拍摄的视频或图片数据传输到服务器上进行处理或存储。

首先定义了IP摄像头的地址,然后使用OpenCV库的VideoCapture函数打开摄像头。接着,使用循环读取视频流数据,并在每一帧数据上进行处理。在处理完视频帧后,使用OpenCV库的imencode函数将视频帧转换为JPEG格式的图像数据,并使用Python的base64库将图像数据编码为base64格式的字符串。最后,将base64编码的字符串上传到服务器。

在实际应用中,需要根据具体的需求对上传数据的格式和方式进行调整。例如,可以使用HTTP协议将数据上传到服务器,或者使用WebSocket协议实现实时数据传输。同时,还需要考虑数据的安全性和稳定性,比如使用SSL加密协议保护数据传输,或者使用缓冲区和重传机制保证数据的可靠性。

但这里只是一个简单的demo,如果要应用到项目上,则要考虑以上的各种因素。

import cv2
import datetime
import time
import requests
import base64
import numpy as np

def image_to_base64(image_np):
    image = cv2.imencode('.jpg', image_np)[1]
    base64_data = str(base64.b64encode(image))[2:-1]
    return base64_data


def base64_to_image(base64_code):
    img_data = base64.b64decode(base64_code)
    img_array = np.frombuffer(img_data, np.uint8)
    img = cv2.imdecode(img_array, cv2.COLOR_RGB2BGR)

    return img


class Camera_picture:

    def __init__(self):
        self.user = "admin"

        self.pwd = "dahua12345"

        self.ip = "192.168.0.xxx:xxx"

        self.file_path = "./"

        self.name = "camera"

    def dahua(self):
        video_stream_path = f"rtsp://{self.user}:{self.pwd}@{self.ip}/cam/realmonitor?channel=1&subtype=0"

        cap = cv2.VideoCapture(video_stream_path)  # 连接摄像头

        print('IP camera open : {}'.format(cap.isOpened()))

        return cap

    def timing_screenshot(self):
        cap = self.dahua()
        if cap.isOpened():
            cv2.namedWindow(self.name, flags=cv2.WINDOW_FREERATIO)
            last_time = datetime.datetime.now()
            while(True):
                ret, frame = cap.read()
                frame = cv2.resize(frame, (500, 300))
                cv2.imshow(self.name, frame)

                cur_time = datetime.datetime.now()
                name = self.file_path + str(time.time()) + ".jpg"
                if (cur_time - last_time).seconds >= 10:
                    cv2.imwrite(name, cap.read()[1])
                    last_time = cur_time
                    print("Image saved successfully!")

                if cv2.waitKey(1) & 0xFF == ord('q'):
                    break

            cap.release()
            cv2.destroyAllWindows()
        else:
            print("Camera connection failed. Please check the configuration!")

    def manual_screenshot(self):
        cap = self.dahua()
        if cap.isOpened():
            cv2.namedWindow(self.name, flags=cv2.WINDOW_FREERATIO)
            while(True):
                ret, frame = cap.read()
                frame = cv2.resize(frame, (500, 300))
                cv2.imshow(self.name, frame)

                event = cv2.waitKey(1) & 0xFF

                if event == ord('s'):  # 按"S"截取图片
                    name = self.file_path + str(time.time()) + ".jpg"
                    cv2.imwrite(name, cap.read()[1])
                    print("Screen saved successfully!")

                elif event == ord('q'):
                    break

            cap.release()
            cv2.destroyAllWindows()
        else:
            print("Camera connection failed. Please check the configuration!")

    def get_video_stream(self):
        cap = self.dahua()
        if cap.isOpened():
            width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
            height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
            fps = cap.get(cv2.CAP_PROP_FPS)
            # fourcc = int(cap.get(cv2.CAP_PROP_FOURCC))

            # FourCC 是用于指定视频编解码器的4字节代码
            # fourcc = cv2.VideoWriter_fourcc(*"MJPG")
            # writer = cv2.VideoWriter(f"{self.file_path}{str(time.time())}.mp4", fourcc, fps, (width, height))

            while(True):
                ret, frame = cap.read()
                if not ret:  # 返回False退出循环
                    break

                # writer.write(frame)  # 视频保存

                # frame = cv2.resize(frame, (500, 300))
                # cv2.imshow(self.name, frame)

                img_code = image_to_base64(frame)
                data = {'img': img_code}
                resp = requests.post("http://127.0.0.1:5004/camera_input", data=data)
                print(resp.content)

                if 0xFF == ord('q'):
                    break

            cap.release()
            cv2.destroyAllWindows()
        else:
            print("Camera connection failed. Please check the configuration!")

    def read_video(self,):
        cap = self.dahua()
        if cap.isOpened():
            key_frame = 2
            j = 0
            while True:
                if key_frame >= 1:
                    cap.set(cv2.CAP_PROP_POS_FRAMES, j)
                    j += key_frame
                    hasFrame, frame = cap.read()
                    if not hasFrame:
                        break

                img_code = image_to_base64(frame)
                data = {'img': img_code}
                resp = requests.post("http://127.0.0.1:5004/camera_input", data=data)
                print(resp.content)
                # cv2.imshow('show', frame)
                # if cv2.waitKey(1) & 0xFF == ord('q'):
                #     break


if __name__ == '__main__':
    run = Camera_picture()
    # run.timing_screenshot()
    # run.get_video_stream()
    # run.manual_screenshot()
    run.read_video()

二、目标识别

这里用来演示的目标识别是git上一个开源代码,可以到这个里下载代码:https://github.com/Sharpiless/Yolov5-deepsort-inference

下载代码,配置下环境,然后运行python demo.py,代码运行效果如下:

 三、服务器端

服务端的代码是接收到数据流之后,进行解码操作,然后使用yolov5模型进行推理。这个过程可以分为以下几个步骤:

1. 接收数据流:服务端通过网络接口接收客户端发送的数据流。

2. 解码数据流:服务端对接收到的数据流进行解码操作,将其转换为图像数据。

3. 模型推理:服务端使用yolov5模型对预处理后的图像数据进行推理,得到目标检测结果。

需要注意的是,服务端的代码需要具备高效的数据处理能力和模型推理能力,以保证实时性和准确性。同时,服务端的代码还需要考虑并发处理和多线程处理等问题,以提高系统的吞吐量和并发性能。

from flask import Flask, request
import base64
import numpy as np
from gevent import pywsgi
import cv2, argparse
import imutils
from AIDetector_pytorch import Detector

det = Detector()
func_status = {}
func_status['headpose'] = None

app = Flask(__name__)
@app.route('/camera_input', methods=['POST'])
def camera_input():
    if request.method == 'POST':
        input_data = request.form.get('img')
        cv_img = base64_to_image(input_data)
        result = det.feedCap(cv_img, func_status)
        result = result['frame']
        result = imutils.resize(result, height=500)

        cv2.imshow('src',result)
        cv2.waitKey(24)

        return 'ok'

def image_to_base64(image_np):
    image = cv2.imencode('.jpg', image_np)[1]
    base64_data = str(base64.b64encode(image))[2:-1]
    return base64_data


def base64_to_image(base64_code):
    img_data = base64.b64decode(base64_code)
    img_array = np.frombuffer(img_data, np.uint8)
    img = cv2.imdecode(img_array, cv2.COLOR_RGB2BGR)

    return img

if __name__ == "__main__":
    print('Statrt server----------------')
    server = pywsgi.WSGIServer(('127.0.0.1', 5004), app)
    server.serve_forever()

摄像头视频和图像处理软件-VideoandImageStudio1.0.zip 本帖最后由 jacket2015 于 2015-2-18 00:10 编辑 MATLAB视频和图像处理软件 功能描述: 1、 本软件具有利用摄像头抓拍图像和视频的功能。可以设定抓拍的图像的格式(gif,tif, png, jpg, bmp),抓拍时,可以设定总共抓拍的次数,以及抓拍的间隔时间,抓拍的间隔时间可以短到小于0.1秒。抓拍的文件将自动保存,保存的文件大小没有限制,只要计算机的硬盘还有空间就可以一直保存。也可以保存为无声音的视频,这时候也需要设定总共拍摄的时间,以及每秒中拍摄的图片的个数。文件自动保存为AVI格式,保存的文件大小没有限制。2、 本软件具有合并和分割图集的功能。可以将不同格式,不同像素的图片合并为一个多帧图片文件。被合并的文件支持gif, tif, png, jpg, bmp等格式,最后合并成gif或者tif格式。支持用户设置被合并的文件的顺序,支持不同的文件。比如被合并的文件中,有文件本省就是一个多帧图片文件,这时候也也可以一起合并。具有添加,删除,上移一位,下移一位等排列被合并文件的功能。如果合并为gif动画,支持用户设定的播放时间间隔。同时也支持将一个多帧图片文件(gif或者tif)分散为多个单帧图片文件。软件附带图片浏览功能,可以浏览gif,tif, png, jpg, bmp等格式的文件,如果被浏览的文件为一个多帧图片文件,则按照一定时间间隔播放这个多帧图片文件。3、 本软件具有视频裁剪和播放功能。支持视频和声频同时播放,播放进度条显示当前播放进度,可以同时暂停和继续视频和声频播放,支持从给定的帧数开始播放至给定的结束播放帧数。支持从视频中截取某些帧的选定区域组成新的视频文件,同时提取选出的这些图像帧相对应的声音信息。用户可以获得独立的图像和声音文件,以备其他商业软件合并成一个文件。支持播放视频的单独声音信息,可以设定播放的频率以及范围。4、 后续功能进一步开发附件
### STM32 使用笔记本摄像头实现人脸检测的方法 #### 设备连接与配置 为了使STM32能够利用笔记本电脑的USB接口访问其内置摄像头,通常需要通过USB转UART桥接器或其他兼容设备建立通信链路。然而,在实际应用中,更常见的是采用独立运行的方式——即让嵌入式系统直接处理视频流并执行人脸检测算法。 对于基于STM32的人脸识别项目来说,可以考虑使用带有MIPI CSI-2接口的支持模块或扩展板来接入专用相机模组;而对于想要借助PC资源的情况,则可通过网络传输图像帧给微控制器进行后续操作[^1]。 #### 图像获取方式 当决定从外部源接收影像资料时,一种可行方案是在主机端编写Python脚本调用OpenCV库读取实时画面,并将其编码成JPEG格式发送至目标单片机: ```python import cv2 from socket import * serverPort = 12000 serverSocket = socket(AF_INET, SOCK_DGRAM) serverSocket.bind(('', serverPort)) cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() _, jpeg = cv2.imencode('.jpg', frame) data = jpeg.tobytes() serverSocket.sendto(data, ('<STM32 IP Address>', clientPort)) ``` 上述代码片段展示了如何创建UDP服务器监听特定端口上的请求并将捕获到的画面序列化后向外广播[^2]。 #### 数据预处理阶段 一旦成功接收到图片包之后,下一步便是解析这些二进制串恢复原始结构以便进一步分析。由于大多数轻量化神经网络框架都支持固定尺寸输入张量的要求,因此还需要调整分辨率大小匹配预期规格: ```c++ #include <jpeglib.h> // ...其他必要的头文件... void decode_jpeg(const uint8_t* buffer, size_t length){ struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; FILE *infile; /* source file */ JSAMPARRAY buffer_out; /* Output row buffer */ int row_stride; /* physical row width in output buffer */ cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_mem_src(&cinfo, (unsigned char*)buffer, length); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); row_stride = cinfo.output_width * cinfo.output_components; buffer_out = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1); while(cinfo.output_scanline < cinfo.output_height){ jpeg_read_scanlines(&cinfo, buffer_out, 1); // 对每一行解码后的像素值做相应变换... } jpeg_finish_decompress(&cinfo); } ``` 这段C++程序说明了怎样运用`libjpeg-turbo`库完成JPEG压缩格式向BMP位图样式的转换过程[^3]。 #### 应用人脸检测模型 最后一步涉及加载预先训练好的权重参数并对传入的数据集实施推理预测动作。考虑到功耗预算以及存储空间等因素的影响,推荐选用诸如Tiny-YOLOv4或者MobileNetV3这样的紧凑型架构作为基础构建单元之一。值得注意的是,尽管MCUNet在某些方面表现出色,但对于ARM Cortex-M系列而言可能仍显庞大复杂,故需谨慎评估具体需求后再作定夺。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知来者逆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值