Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
1 result

Target

Select target project
  • thiefsil/camera-node
1 result
Select Git revision
  • master
1 result
Show changes
Commits on Source (2)
...@@ -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;
......
#!bin/bash #!bin/bash
FILE_NAME="camera" CAMERA_FILE="camera"
SERVICE_FILE="/etc/systemd/system/${FILE_NAME}.service" SERVICE_FILE="/etc/systemd/system/camera.service"
FILE_NAME2="ocr" OCR_FILE="ocr.py"
SERVICE_FILE2="/etc/systemd/system/${FILE_NAME2}.service" SERVICE_FILE2="/etc/systemd/system/ocr.service"
USER_NAME="pi" USER_NAME="pi"
EXEC_PATH="./camera-node-control/${FILE_NAME}.cpp" CAMERA_PATH="$(pwd)/camera-node-control"
EXEC_PATH2="./camera-node-ocr/${FILE_NAME2}.py" OCR_PATH="$(pwd)/camera-node-ocr"
cat <<EOF | sudo tee $SERVICE_FILE > /dev/null cat <<EOF | sudo tee $SERVICE_FILE > /dev/null
[Unit] [Unit]
Description=Camera Description=Camera
Atfer=network.target After=network.target
[Service] [Service]
ExecStart=$EXEC_PATH WorkingDirectory=$CAMERA_PATH
ExecStart=$CAMERA_PATH/$CAMERA_FILE
Restart=always Restart=always
RestartSec=5s
User=$USER_NAME User=$USER_NAME
[Install] [Install]
WantedBy=multi-user.targetrpi WantedBy=multi-user.target
EOF EOF
sudo systemctl daemon-reload sudo systemctl daemon-reload
sudo systemctl enable ${FILE_NAME}.service sudo systemctl enable camera.service
sudo systemctl start ${FILE_NAME}.service sudo systemctl start camera.service
sudo systemctl status ${FILE_NAME}.service sudo systemctl status camera.service
cat <<EOF | sudo tee $SERVICE_FILE2 > /dev/null cat <<EOF | sudo tee $SERVICE_FILE2 > /dev/null
[Unit] [Unit]
Description=Ocr Description=Ocr
Atfer=network.target After=network.target
[Service] [Service]
ExecStart=python3 $EXEC_PATH2 WorkingDirectory=$OCR_PATH
ExecStart=/bin/bash -c "source $OCR_PATH/venv/bin/activate && python3 $OCR_PATH/$OCR_FILE"
Restart=always Restart=always
RestartSec=5s
User=$USER_NAME User=$USER_NAME
[Install] [Install]
WantedBy=multi-user.targetrpi WantedBy=multi-user.target
EOF EOF
sudo systemctl daemon-reload sudo systemctl daemon-reload
sudo systemctl enable ${FILE_NAME2}.service sudo systemctl enable ocr.service
sudo systemctl start ${FILE_NAME2}.service sudo systemctl start ocr.service
sudo systemctl status ${FILE_NAME2}.service sudo systemctl status ocr.service