-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathCamera.cpp
More file actions
193 lines (167 loc) · 5.87 KB
/
Camera.cpp
File metadata and controls
193 lines (167 loc) · 5.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include "capture/Camera.h"
#include <ntcore_cpp.h>
#include <iostream>
#include <thread>
// Constructor: Initializes and opens the camera using OpenCV
Camera::Camera(const std::string& device_path, const std::string& hardwareID,
const int width, const int height)
: m_hardwareID(hardwareID), m_device_path(device_path),
m_req_width(width), m_req_height(height) {
logInfo("Initializing with OpenCV backend...");
// Initial camera connection and configuration
attemptReconnect();
}
// Destructor: Releases the camera resource
Camera::~Camera() {
logInfo("Releasing camera...");
if (m_capture.isOpened()) {
m_capture.release();
}
}
// Captures a new frame from the camera
bool Camera::getFrame(
cv::Mat& frame,
int64_t& timestamp) {
if (!isConnected()) {
m_is_connected = false;
return false;
}
// Atomically grab and retrieve the frame.
if (m_capture.read(frame)) {
timestamp = nt::Now();
m_is_connected = true;
return true; // Frame captured successfully.
}
logError("Failed to capture frame. The camera may have been disconnected.");
m_is_connected = false;
return false;
}
// Sets the camera's exposure property
bool Camera::setExposure(const int value) {
if (!isConnected()) {
m_last_exposure = value; // Store even if not connected, will apply on reconnect
return false;
}
logInfo("Setting exposure to " + std::to_string(value));
if (!m_capture.set(cv::CAP_PROP_EXPOSURE, value)) {
logError("Failed to set exposure.");
return false;
}
m_last_exposure = value;
return true;
}
// Sets the camera's brightness property
bool Camera::setBrightness(const int value) {
if (!isConnected()) {
m_last_brightness = value; // Store even if not connected, will apply on reconnect
return false;
}
logInfo("Setting brightness to " + std::to_string(value));
if (!m_capture.set(cv::CAP_PROP_BRIGHTNESS, value)) {
logError("Failed to set brightness.");
return false;
}
m_last_brightness = value;
return true;
}
// Checks if the camera is open and ready for use
bool Camera::isConnected() const { return m_capture.isOpened(); }
std::string Camera::getFormat() {
if (!isConnected()) {
return "";
}
int fourcc = static_cast<int>(m_capture.get(cv::CAP_PROP_FOURCC));
if (fourcc == 0) {
return "";
}
std::string formatStr;
formatStr += (fourcc & 0XFF);
formatStr += ((fourcc >> 8) & 0XFF);
formatStr += ((fourcc >> 16) & 0XFF);
formatStr += ((fourcc >> 24) & 0XFF);
return formatStr;
}
// Helper for logging informational messages
void Camera::logInfo(const std::string& message) const {
std::cout << "[INFO] Camera (" << m_hardwareID << "): " << message
<< std::endl;
}
// Helper for logging error messages
void Camera::logError(const std::string& message) const {
std::cerr << "[ERROR] Camera (" << m_hardwareID << "): " << message
<< std::endl;
}
void Camera::configureCamera() {
if (!m_capture.isOpened()) {
logError("Cannot configure camera: stream not open.");
return;
}
logInfo("Configuring camera properties...");
// Set the desired frame dimensions.
if (m_capture.set(cv::CAP_PROP_FRAME_WIDTH, m_req_width)) {
logInfo("Set frame width to " + std::to_string(m_req_width));
} else {
logError("Warning: Failed to set frame width.");
}
if (m_capture.set(cv::CAP_PROP_FRAME_HEIGHT, m_req_height)) {
logInfo("Set frame height to " + std::to_string(m_req_height));
} else {
logError("Warning: Failed to set frame height.");
}
// --- Disable Auto Properties ---
// It's crucial to disable auto-exposure and auto-white-balance for consistent
// imaging. Note: For V4L2, a value of '1' often means 'manual mode' (auto
// off).
if (m_capture.set(cv::CAP_PROP_AUTO_EXPOSURE, 1)) {
logInfo("Disabled auto-exposure (set to manual mode).");
} else {
logError("Warning: Could not disable auto-exposure.");
}
// Apply last known exposure and brightness settings
if (m_last_exposure != -1) {
setExposure(m_last_exposure);
}
if (m_last_brightness != -1) {
setBrightness(m_last_brightness);
}
// Log the actual format the camera has settled on.
if (const int fourcc = static_cast<int>(m_capture.get(cv::CAP_PROP_FOURCC));
fourcc != 0) {
// Decode the FourCC integer into a human-readable string.
std::string formatStr;
formatStr += (fourcc & 0XFF);
formatStr += ((fourcc >> 8) & 0XFF);
formatStr += ((fourcc >> 16) & 0XFF);
formatStr += ((fourcc >> 24) & 0XFF);
logInfo("Actual camera format in use: " + formatStr);
} else {
logError("Could not retrieve camera format.");
}
// Retrieve the actual frame dimensions, as the camera might not support the
// exact requested size.
m_width = static_cast<int>(m_capture.get(cv::CAP_PROP_FRAME_WIDTH));
m_height = static_cast<int>(m_capture.get(cv::CAP_PROP_FRAME_HEIGHT));
logInfo("Actual stream resolution: " + std::to_string(m_width) + "x" +
std::to_string(m_height));
}
bool Camera::attemptReconnect() {
if (m_capture.isOpened()) {
m_capture.release();
logInfo("Released existing camera connection.");
}
logInfo("Attempting to open camera stream at path " + m_device_path);
// Open the camera stream using the specified device path and the Video4Linux
// backend. Using V4L2 is often more reliable on Linux for setting properties.
m_capture.open(m_device_path, cv::CAP_V4L2);
m_capture.set(cv::CAP_PROP_BUFFERSIZE, 4);
m_capture.set(cv::CAP_PROP_FPS, 60);
m_capture.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('Y', 'U', 'Y', 'V'));
if (!m_capture.isOpened()) {
logError("Failed to open camera stream at path " + m_device_path + ". Retrying in 1 second...");
std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait before retrying
return false;
}
logInfo("Camera stream opened successfully.");
configureCamera();
return true;
}