写这个是为了解决vscode远程服务时,无法实时显示正在处理的图像,想知道就得保存后才能看。现在是基础示例,你可以根据自己的要求封装。
为了方便 接收端使用的python
发送端 cpp
这里面为了方便快,使用了缩放和压缩
文件结构
account_dir-> httplib.h
media-> cat.png
CMakeLists.txt
first_cmake.cpp
first_cmake.cpp 文件内容
cpp
#include <iostream>
#include <opencv2/opencv.hpp>
#include "httplib.h"
int main()
{
// 使用imread函数读取图片,和Python用法类似
// 读取的数据保存在Mat类型的变量image中,Mat是opencv中的图像数据结构,类似numpy中的ndarray
cv::Mat image = cv::imread("./media/cat.png"); // 在终端输入命令: ./build/open_domo ./media/cat.jpg
// cv::Mat image = cv::imread("./media/cat.jpg", 0); // 0代表 直接加载灰度图
// cv::Mat image = cv::imread(argv[1]);
cv::Mat resize;
cv::resize(image, resize, cv::Size(640, 640));
// 判断图像是否读取成功,返回true表示失败
if (resize.empty()) // 使用!image.data也可以判断
{
std::cout << "无法读取图片" << std::endl;
return 1;
}
std::cout << "图片高度: " << image.rows << "宽度: " << image.cols << std::endl;
// 1. 创建HTTP客户端
httplib::Client client("192.168.11.100", 25565);
// 2. 检查客户端是否创建成功
if (!client.is_valid()) {
std::cout << "无法连接到 192.168.11.100:25565" << std::endl;
return 1;
}
// 循环10次是为了测试
for (int i=1;i<=10;i++){
std::vector<uchar> buffer;
// PNG压缩级别:0=无压缩(文件大),9=最大压缩(文件小,编码慢)
std::vector<int> png_params = {cv::IMWRITE_PNG_COMPRESSION, 9}; // 无压缩
cv::imencode(".png", resize, buffer, png_params);
std::string image_data(buffer.begin(), buffer.end());
// // 编码为二进制
// std::vector<uchar> buffer;
// cv::imencode(".png", image, buffer);
// // 转为字符串
// std::string image_data(buffer.begin(), buffer.end());
// // 4. 发送POST请求
// // "image/jpeg":这是JPEG图像格式
// // "image/png":这是PNG图像格式
// // "text/plain":这是纯文本
// // "application/json":这是JSON数据
httplib::Result result = client.Post("/upload", image_data, "image/png");
// auto res = client.Post("/upload", image_data, "image/jpeg");
// 检查请求结果
// if (result) {
// // 请求成功,检查状态码
// if (result->status == 200) {
// std::cout << "请求成功: " << result->body << std::endl;
// } else {
// std::cout << "服务器返回错误: " << result->status << std::endl;
// std::cout << "响应内容: " << result->body << std::endl;
// }
// } else {
// // 请求失败
// auto err = result.error();
// std::cout << "HTTP请求失败: " << httplib::to_string(err) << std::endl;
// }
}
//标志位
// std::cout << "flags:" << image.flags << std::endl;
//图像尺寸
// std::cout << "size:" << image.size << std::endl;
// 图像通道数
//std::cout << "channels" << input_image.channels() << std::endl;
//维度
// std::cout << "dims:" << image.dims << std::endl;
// // 保存图像
// cv::imwrite("./gray_image.jpg", image);
// imshow显示图像
// cv::imshow("opencv demo", image);
// 等待按键
// cv::waitKey(0);
return 0;
}
CMakeLists.txt 文件内容
bash
# 最低版本要求
cmake_minimum_required(VERSION 3.10)
# 项目信息
project(demo_opencv)
# 查找opencv库(REQUIRED表示找不到就终止编译)
find_package(OpenCV REQUIRED)
# 给自己写个提示 也方便查找报错原因
# 关键修复:变量名是 OpenCV_FOUND(大小写敏感)
if (OpenCV_FOUND)
# 找到后打印一些信息
message(STATUS "openCV library status:")
message(STATUS " version: ${OpenCV_VERSION}") # 版本
message(STATUS " libraries: ${OpenCV_LIBS}") # 修复:库名称应该用 OpenCV_LIBS(你之前写的是 INCLUDE_DIRS)
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}") # 库的头文件路径
else()
# 找不到
message(STATUS "openCV library status: !!!!!! not found !!!!!!!")
endif()
# 添加可执行文件
add_executable(first_cmake "./first_cmake.cpp")
# 添加头文件
target_include_directories(
first_cmake
PRIVATE
${OpenCV_INCLUDE_DIRS}
"${CMAKE_CURRENT_SOURCE_DIR}/account_dir" # 添加你的头文件所在目录
)
# 添加链接
target_link_libraries(first_cmake PRIVATE ${OpenCV_LIBS})
run.sh 文件内容
bash
rm -r build
mkdir build
cd build
cmake ..
cd ../
cmake --build build
./build/first_cmake
接收端 python
图像关闭时,鼠标点击叉号,不要使用按键。
python
from flask import Flask, request, jsonify
import cv2
import numpy as np
import os
app = Flask(__name__)
@app.route('/upload', methods=['POST'])
def receive_image():
while True:
"""
标准图像接收接口
"""
try:
# 1. 获取原始图像字节数据
image_bytes = request.data
print(f"收到数据大小: {len(image_bytes)} 字节")
# 2. 转换为OpenCV格式
nparr = np.frombuffer(image_bytes, np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
if img is None:
print("错误: 无法解码图像数据")
return jsonify({'status': 'error', 'message': '无法解码图像'}), 400
# 3. 获取图像信息
height, width = img.shape[:2]
channels = img.shape[2] if len(img.shape) > 2 else 1
print(f"解码成功: {width}x{height}, 通道数: {channels}")
print(f"图像数据类型: {img.dtype}")
print(f"图像最大值: {img.max()}, 最小值: {img.min()}")
# 4. 保存图像
# 保存原始接收到的图像
# cv2.imwrite('received_image.png', img)
# print(f"图像已保存为: received_image.png")
# 调整宽高(再次运行也只会加载你调整后的宽高)
cv2.namedWindow("1", cv2.WINDOW_NORMAL)
cv2.imshow("1", img) # 必要参数:名字和变量名
cv2.waitKey(0) # 括号中0=任意键终止,单位为毫秒级别
# 6. 返回响应
return jsonify({
'status': 'success',
'width': width,
'height': height,
'channels': channels,
'size_bytes': len(image_bytes)
})
except Exception as e:
print(f"服务器错误: {str(e)}")
return jsonify({'status': 'error', 'message': str(e)}), 500
if __name__ == '__main__':
print("服务器启动在 http://0.0.0.0:25565")
print("等待接收图像...")
app.run(host='0.0.0.0', port=25565, debug=True)