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

Target

Select target project
  • thiefsil/camera-node
1 result
Select Git revision
Show changes
Commits on Source (2)
......@@ -11,7 +11,6 @@
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <libcamera/libcamera.h>
#include <opencv2/opencv.hpp>
#include <iomanip>
#include <stdexcept>
......@@ -19,12 +18,11 @@
#include <arpa/inet.h>
using namespace std;
using namespace libcamera;
using namespace GPIO;
#define BUFFER_SIZE 1024
#define SERVER_ADDR "127.0.0.1"
#define SERVER_ADDR "192.168.121.4"
#define SERVER_PORT 12345
#define POUT 535 // 초음파 트리거 핀 (GPIO23)
......@@ -71,86 +69,6 @@ int server_socket, python_socket; // 서버 소켓 및 파이썬 소켓
bool detected = false; // 차량 감지 여부
bool fireAlert = false; // 화재 경보 여부
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) {
for (size_t idx = 0; idx < rects.size(); idx++) {
......@@ -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) {
const FrameBuffer* buffer = request->buffers().begin()->second;
const FrameBuffer::Plane& plane = buffer->planes().front();
// 에코 핀 신호 대기
while (GPIORead(PIN) == 0) start_t = clock();
while (GPIORead(PIN) == 1) end_t = clock();
void* memory = mmap(nullptr, plane.length, PROT_READ, MAP_SHARED, plane.fd.get(), 0);
if (memory != MAP_FAILED) {
cv::Mat raw(800, 1600, CV_8UC2, memory);
cv::Mat bgr;
cv::cvtColor(raw, bgr, cv::COLOR_YUV2BGR_YUYV);
double time = (double) (end_t - start_t) / CLOCKS_PER_SEC; // 시간 계산
double distance = time / 2 * 34000; // cm 단위 거리 계산
vector<unsigned char> jpeg_buffer;
vector<int> params = {cv::IMWRITE_JPEG_QUALITY, 90};
cv::imencode(".jpg", bgr, jpeg_buffer, params);
cout << distance << "cm" << endl;
if (!detected && distance <= DISTANCE) { // 10cm 이하 -> 차량 접근
detected = true;
cout << "차량 감지: " << distance << "cm" << endl;
// 현재 시간 타임스탬프
auto now = chrono::system_clock::now();
......@@ -347,65 +300,28 @@ void requestComplete(Request* request) {
string timestamp_str = timestamp.str();
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 (file) {
file.write(reinterpret_cast<char*>(jpeg_buffer.data()), jpeg_buffer.size());
file.close();
if (system(cmd.c_str()) == 0) {
cout << "이미지 저장: " << image_filename << endl;
} else {
cerr << "이미지 저장 실패: " << image_filename << endl;
}
munmap(memory, plane.length);
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() {
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;
// 서버 노드 소켓 생성
......@@ -468,13 +384,6 @@ int main() {
close(python_socket);
GPIOUnexport(POUT);
GPIOUnexport(PIN);
camera->requestCompleted.disconnect();
camera->stop();
camera->release();
camera.reset();
allocator.free(stream);
cm->stop();
} catch (const exception& e) {
cerr << "Error: " << e.what() << endl;
return 1;
......
#!bin/bash
FILE_NAME="camera"
SERVICE_FILE="/etc/systemd/system/${FILE_NAME}.service"
FILE_NAME2="ocr"
SERVICE_FILE2="/etc/systemd/system/${FILE_NAME2}.service"
CAMERA_FILE="camera"
SERVICE_FILE="/etc/systemd/system/camera.service"
OCR_FILE="ocr.py"
SERVICE_FILE2="/etc/systemd/system/ocr.service"
USER_NAME="pi"
EXEC_PATH="./camera-node-control/${FILE_NAME}.cpp"
EXEC_PATH2="./camera-node-ocr/${FILE_NAME2}.py"
CAMERA_PATH="$(pwd)/camera-node-control"
OCR_PATH="$(pwd)/camera-node-ocr"
cat <<EOF | sudo tee $SERVICE_FILE > /dev/null
[Unit]
Description=Camera
Atfer=network.target
After=network.target
[Service]
ExecStart=$EXEC_PATH
WorkingDirectory=$CAMERA_PATH
ExecStart=$CAMERA_PATH/$CAMERA_FILE
Restart=always
RestartSec=5s
User=$USER_NAME
[Install]
WantedBy=multi-user.targetrpi
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable ${FILE_NAME}.service
sudo systemctl start ${FILE_NAME}.service
sudo systemctl status ${FILE_NAME}.service
sudo systemctl enable camera.service
sudo systemctl start camera.service
sudo systemctl status camera.service
cat <<EOF | sudo tee $SERVICE_FILE2 > /dev/null
[Unit]
Description=Ocr
Atfer=network.target
After=network.target
[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
RestartSec=5s
User=$USER_NAME
[Install]
WantedBy=multi-user.targetrpi
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable ${FILE_NAME2}.service
sudo systemctl start ${FILE_NAME2}.service
sudo systemctl status ${FILE_NAME2}.service
sudo systemctl enable ocr.service
sudo systemctl start ocr.service
sudo systemctl status ocr.service