Raspberry Pi로 실시간 영상 처리
카메라 모듈 사용법
OpenCV 설치
apt install libopencv-dev
OpenCV 코드
g++ hud0.cc -o hud.out
pkg-config --cflags --libs opencv4`
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
// 카메라 열기
cv::VideoCapture cap(0); // 0은 기본 카메라를 의미
if (!cap.isOpened()) {
std::cerr << "카메라를 열 수 없습니다." << std::endl;
return -1;
}
while (true) {
cv::Mat frame;
// 카메라로부터 프레임 읽기
cap >> frame;
if (frame.empty()) {
std::cerr << "프레임을 읽을 수 없습니다." << std::endl;
break;
}
// "hello world" 텍스트 추가
std::string text = "hello world";
cv::Point position(50, 50); // 텍스트의 위치 (x, y)
int font = cv::FONT_HERSHEY_SIMPLEX; // 글꼴
double fontScale = 1.0; // 글꼴 크기
cv::Scalar color(0, 255, 0); // 초록색 (B, G, R)
int thickness = 2; // 텍스트 두께
cv::putText(frame, text, position, font, fontScale, color, thickness);
// 결과 영상 표시
cv::imshow("Camera", frame);
// 'q'를 누르면 종료
if (cv::waitKey(1) == 'q') {
break;
}
}
// 자원 해제
cap.release();
cv::destroyAllWindows();
return 0;
}
영상 데이터를 전송
#include <opencv2/opencv.hpp>
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 8080
int main() {
// 카메라 열기
cv::VideoCapture cap(0);
if (!cap.isOpened()) {
std::cerr << "카메라를 열 수 없습니다." << std::endl;
return -1;
}
// 소켓 생성
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
std::cerr << "소켓 생성 실패" << std::endl;
return -1;
}
// 서버 주소 설정
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr("192.168.1.2"); // 수신 PC의 IP 주소로 변경
// 서버에 연결
if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
std::cerr << "서버 연결 실패" << std::endl;
return -1;
}
std::cout << "서버에 연결되었습니다." << std::endl;
while (true) {
cv::Mat frame;
cap >> frame; // 프레임 캡처
if (frame.empty()) {
std::cerr << "프레임 캡처 실패" << std::endl;
break;
}
// 프레임을 JPEG로 인코딩
std::vector<uchar> buffer;
cv::imencode(".jpg", frame, buffer);
// 버퍼 크기 전송
int buffer_size = buffer.size();
send(sock, &buffer_size, sizeof(buffer_size), 0);
// 프레임 데이터 전송
send(sock, buffer.data(), buffer_size, 0);
// 'q'를 누르면 종료
if (cv::waitKey(1) == 'q') {
break;
}
}
// 자원 해제
close(sock);
cap.release();
return 0;
}
영상 데이터를 수신
#include <opencv2/opencv.hpp>
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 8080
int main() {
// 소켓 생성
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == 0) {
std::cerr << "소켓 생성 실패" << std::endl;
return -1;
}
// 서버 주소 설정
struct sockaddr_in address;
int addrlen = sizeof(address);
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY; // 모든 네트워크 인터페이스에서 수신
address.sin_port = htons(PORT);
// 소켓 바인딩
if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
std::cerr << "바인딩 실패" << std::endl;
return -1;
}
// 연결 대기
if (listen(server_fd, 3) < 0) {
std::cerr << "연결 대기 실패" << std::endl;
return -1;
}
std::cout << "클라이언트 연결 대기 중..." << std::endl;
int new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
if (new_socket < 0) {
std::cerr << "클라이언트 연결 실패" << std::endl;
return -1;
}
std::cout << "클라이언트 연결됨!" << std::endl;
while (true) {
// 버퍼 크기 수신
int buffer_size = 0;
recv(new_socket, &buffer_size, sizeof(buffer_size), 0);
// 데이터 수신
std::vector<uchar> buffer(buffer_size);
recv(new_socket, buffer.data(), buffer_size, 0);
// JPEG 디코딩
cv::Mat frame = cv::imdecode(buffer, cv::IMREAD_COLOR);
if (frame.empty()) {
std::cerr << "프레임 디코딩 실패" << std::endl;
break;
}
// 화면에 출력
cv::imshow("Received Frame", frame);
// 'q'를 누르면 종료
if (cv::waitKey(1) == 'q') {
break;
}
}
// 자원 해제
close(new_socket);
close(server_fd);
return 0;
}
메모리 할당 실패하는 문제
module v4l2src0 reported failed to allocate required memory
- OpenCV의 VideoCapture는 단순 V4L2 device들만 지원한다.
- V4L2(Video For Linux 2) - Linux 운영체제가 영상 장치의 기능을 사용할 수 있게 해주는 커널 프레임워크
- user-space의 앱이 영상 장치(cameras, TV cards)와 상호작용할 수 있는 다양한 API와 driver interface를 제공한다.
- Raspberry Pi OS Bullseye부터 새로운 카메라 스택인
libcamera
가 도입되었다.
libcamera 설치
- 소스코드 다운로드&빌드
git clone https://git.libcamera.org/libcamera/libcamera.git && \
cd libcamera && \
meson setup build && \
ninja -C build install
references
- ChatGPT
- [OpenCV] Get Started
- opencv2 error v4l2src0 reported: Failed to allocate required memory
- V4L2
- Using libcamera in a C++ application