Skip to content
Snippets Groups Projects
Commit d61f0106 authored by 한동현's avatar 한동현
Browse files

refactor(c): libcamera 커맨드라인 명령으로 변경

parent d900d81b
Branches
No related tags found
No related merge requests found
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include <unistd.h> #include <unistd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <libcamera/libcamera.h>
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
#include <iomanip> #include <iomanip>
#include <stdexcept> #include <stdexcept>
...@@ -19,12 +18,11 @@ ...@@ -19,12 +18,11 @@
#include <arpa/inet.h> #include <arpa/inet.h>
using namespace std; using namespace std;
using namespace libcamera;
using namespace GPIO; using namespace GPIO;
#define BUFFER_SIZE 1024 #define BUFFER_SIZE 1024
#define SERVER_ADDR "127.0.0.1" #define SERVER_ADDR "192.168.121.4"
#define SERVER_PORT 12345 #define SERVER_PORT 12345
#define POUT 535 // 초음파 트리거 핀 (GPIO23) #define POUT 535 // 초음파 트리거 핀 (GPIO23)
...@@ -71,86 +69,6 @@ int server_socket, python_socket; // 서버 소켓 및 파이썬 소켓 ...@@ -71,86 +69,6 @@ int server_socket, python_socket; // 서버 소켓 및 파이썬 소켓
bool detected = false; // 차량 감지 여부 bool detected = false; // 차량 감지 여부
bool fireAlert = false; // 화재 경보 여부 bool fireAlert = false; // 화재 경보 여부
pthread_t sensor_thread, receive_thread; pthread_t sensor_thread, receive_thread;
shared_ptr<Camera> camera;
unique_ptr<CameraManager> cm;
unique_ptr<Request> request;
// 서버 메시지 수신 스레드
void* receive_message(void* arg) {
char buffer[BUFFER_SIZE];
while (true) {
auto read_bytes = read(server_socket, buffer, BUFFER_SIZE - 1);
if (read_bytes <= 0) {
cout << "서버와의 연결이 종료되었습니다." << endl;
close(server_socket);
exit(0);
}
buffer[read_bytes] = '\0';
cout << "서버로부터 받은 메시지: " << buffer << endl;
string msg(buffer);
msg = msg.substr(0, msg.find_first_of("\r\n"));
if (msg == "0-FIRE") {
fireAlert = true;
cout << "화재 경보가 발생했습니다." << endl;
} else if (msg == "0-CLEAR") {
fireAlert = false;
cout << "화재 경보가 해제되었습니다." << endl;
}
}
return nullptr;
}
// 초음파 센서 측정 스레드
void* ultrasonic_sensor(void *arg) {
clock_t start_t, end_t;
while (1) {
// 초음파 센서 측정
GPIOWrite(POUT, Value::HIGH);
usleep(10);
GPIOWrite(POUT, Value::LOW);
// 에코 핀 신호 대기
while (GPIORead(PIN) == 0) start_t = clock();
while (GPIORead(PIN) == 1) end_t = clock();
double time = (double) (end_t - start_t) / CLOCKS_PER_SEC; // 시간 계산
double distance = time / 2 * 34000; // cm 단위 거리 계산
cout << distance << "cm" << endl;
if (!detected && distance <= DISTANCE) { // 10cm 이하 -> 차량 접근
detected = true;
cout << "차량 감지: " << distance << "cm" << endl;
// 카메라를 시작합니다.
if (camera->start()) {
throw runtime_error("Failed to start camera");
}
// 카메라 촬영
if (camera->queueRequest(request.get()) < 0) {
throw runtime_error("Failed to queue request");
}
this_thread::sleep_for(chrono::milliseconds(2000));
// 카메라 종료
camera->stop();
} else if (detected && distance > 10) { // 10cm 초과 -> 차량 없음
detected = false;
cout << "차량 감지 해제" << endl;
}
usleep(500000); // 0.5초 주기
}
return nullptr;
}
vector<Rect> detect_character(const vector<Rect>& rects) { vector<Rect> detect_character(const vector<Rect>& rects) {
for (size_t idx = 0; idx < rects.size(); idx++) { for (size_t idx = 0; idx < rects.size(); idx++) {
...@@ -323,21 +241,56 @@ void detect_plate(const string& img_path) { ...@@ -323,21 +241,56 @@ void detect_plate(const string& img_path) {
} }
} }
// 서버 메시지 수신 스레드
void* receive_message(void* arg) {
char buffer[BUFFER_SIZE];
while (true) {
auto read_bytes = read(server_socket, buffer, BUFFER_SIZE - 1);
if (read_bytes <= 0) {
cout << "서버와의 연결이 종료되었습니다." << endl;
close(server_socket);
exit(0);
}
buffer[read_bytes] = '\0';
cout << "서버로부터 받은 메시지: " << buffer << endl;
string msg(buffer);
msg = msg.substr(0, msg.find_first_of("\r\n"));
if (msg == "0-FIRE") {
fireAlert = true;
cout << "화재 경보가 발생했습니다." << endl;
} else if (msg == "0-CLEAR") {
fireAlert = false;
cout << "화재 경보가 해제되었습니다." << endl;
}
}
return nullptr;
}
// 초음파 센서 측정 스레드
void* ultrasonic_sensor(void *arg) {
clock_t start_t, end_t;
while (1) {
// 초음파 센서 측정
GPIOWrite(POUT, Value::HIGH);
usleep(10);
GPIOWrite(POUT, Value::LOW);
void requestComplete(Request* request) { // 에코 핀 신호 대기
if (request->status() == Request::RequestComplete) { while (GPIORead(PIN) == 0) start_t = clock();
const FrameBuffer* buffer = request->buffers().begin()->second; while (GPIORead(PIN) == 1) end_t = clock();
const FrameBuffer::Plane& plane = buffer->planes().front();
void* memory = mmap(nullptr, plane.length, PROT_READ, MAP_SHARED, plane.fd.get(), 0); double time = (double) (end_t - start_t) / CLOCKS_PER_SEC; // 시간 계산
if (memory != MAP_FAILED) { double distance = time / 2 * 34000; // cm 단위 거리 계산
cv::Mat raw(800, 1600, CV_8UC2, memory);
cv::Mat bgr;
cv::cvtColor(raw, bgr, cv::COLOR_YUV2BGR_YUYV);
vector<unsigned char> jpeg_buffer; cout << distance << "cm" << endl;
vector<int> params = {cv::IMWRITE_JPEG_QUALITY, 90}; if (!detected && distance <= DISTANCE) { // 10cm 이하 -> 차량 접근
cv::imencode(".jpg", bgr, jpeg_buffer, params); detected = true;
cout << "차량 감지: " << distance << "cm" << endl;
// 현재 시간 타임스탬프 // 현재 시간 타임스탬프
auto now = chrono::system_clock::now(); auto now = chrono::system_clock::now();
...@@ -347,65 +300,28 @@ void requestComplete(Request* request) { ...@@ -347,65 +300,28 @@ void requestComplete(Request* request) {
string timestamp_str = timestamp.str(); string timestamp_str = timestamp.str();
string image_filename = IMAGES_DIR + "/image_" + timestamp_str + ".jpg"; string image_filename = IMAGES_DIR + "/image_" + timestamp_str + ".jpg";
string cmd = "libcamera-still --nopreview --immediate --rotation=180 --width=1296 --height=972 --denoise off -t 1 -o " + image_filename;
ofstream file(image_filename, ios::binary); if (system(cmd.c_str()) == 0) {
if (file) {
file.write(reinterpret_cast<char*>(jpeg_buffer.data()), jpeg_buffer.size());
file.close();
cout << "이미지 저장: " << image_filename << endl; cout << "이미지 저장: " << image_filename << endl;
} else { } else {
cerr << "이미지 저장 실패: " << image_filename << endl; cerr << "이미지 저장 실패: " << image_filename << endl;
} }
munmap(memory, plane.length);
detect_plate(image_filename); detect_plate(image_filename);
} else if (detected && distance > 10) { // 10cm 초과 -> 차량 없음
detected = false;
cout << "차량 감지 해제" << endl;
} }
request->reuse(Request::ReuseBuffers); usleep(500000); // 0.5초 주기
} }
return nullptr;
} }
int main() { int main() {
try { try {
cm = make_unique<CameraManager>();
cm->start();
auto cameras = cm->cameras();
if (cameras.empty()) {
throw runtime_error("No cameras found!");
}
camera = cameras[0];
camera->acquire();
unique_ptr<CameraConfiguration> config = camera->generateConfiguration({StreamRole::StillCapture});
config->orientation = Orientation::Rotate180;
StreamConfiguration &streamConfig = config->at(0);
streamConfig.size = Size(1600, 900);
streamConfig.pixelFormat = formats::YUYV;
streamConfig.bufferCount = 1;
CameraConfiguration::Status status = config->validate();
if (status != CameraConfiguration::Valid) {
throw runtime_error("Camera configuration invalid");
}
camera->configure(config.get());
FrameBufferAllocator allocator(camera);
Stream *stream = streamConfig.stream();
allocator.allocate(stream);
camera->requestCompleted.connect(requestComplete);
const vector<unique_ptr<FrameBuffer>> &buffers = allocator.buffers(stream);
request = camera->createRequest();
if (request->addBuffer(stream, buffers.at(0).get()) < 0) {
throw runtime_error("Failed to add buffer to request");
}
struct sockaddr_in server_addr, python_addr; struct sockaddr_in server_addr, python_addr;
// 서버 노드 소켓 생성 // 서버 노드 소켓 생성
...@@ -468,13 +384,6 @@ int main() { ...@@ -468,13 +384,6 @@ int main() {
close(python_socket); close(python_socket);
GPIOUnexport(POUT); GPIOUnexport(POUT);
GPIOUnexport(PIN); GPIOUnexport(PIN);
camera->requestCompleted.disconnect();
camera->stop();
camera->release();
camera.reset();
allocator.free(stream);
cm->stop();
} catch (const exception& e) { } catch (const exception& e) {
cerr << "Error: " << e.what() << endl; cerr << "Error: " << e.what() << endl;
return 1; return 1;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment