만든 이유
OpenCV를 이용하다 보면, USB 카메라를 사용해야 할 때가 많은데,
연결되어 있는 카메라가 있는지 확인하고, 자동으로 켜주는 카메라 전용 클래스가 있으면 편할 것 같아서.
또, 각각의 카메라 밝기를 키보드 방향키로 변화시켜줄 수 있으면 좋겠다. 싶어서.
게다가 나만의 헤더에 넣어놓고, 필요할때 마다 꺼내쓰면 개꿀일 것 같아서.
특징 및 동작
- 클래스 이름은 ControlCam
- 생성자가 호출되면 CheckCamPort()라는 메서드가 실행된다.
- CheckCamPort()에서는 0~5번 포트를 확인하고, 카메라가 연결되어 있으면, VideoCapture 객체를 생성한다.
- 사용하려면, main문에서 ControlCam 객체 생성하고, while문에서 메서드 RunCam() 작성해줘야함.
메모리를 줄여보고자(라즈베리파이와 같은 소형 컴퓨터는 메모리가 부족하니까... )
VideoCapture과 Mat은 배열을 동적할당하였다.
실행 사진
소스코드
////////////////////////////////////////////////////////////////
// importance : ☆☆☆☆☆
// title : 과제5
// 카메라를 control하기 위한 class를 선언하고 다음 기능을 구현하시오
// 1. 자동 카메라 연결(카메라의 개수를 입력 받음, (default = 1)
// 2. 연결된 카메라의 이미지 반환
// date : 2020.02.05
// writer : jeong
// result : 카메라가 연결된 갯수만큼 창을 띄워서 동시에 카메라 영상을 틀어줌.
// 참고 :
////////////////////////////////////////////////////////////////
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
class ControlCam {
protected:
int CamNum = 0, flag = 0;
VideoCapture* cap = new VideoCapture[6];
Mat* image = new Mat[6];
string Name[6] = { "camera 0","camera 1","camera 2", "camera 3", "camera 4", "camera 5" };
public:
void CheckCamPort() {// 카메라 열렸는지 확인하여 VideoCapture객체 만들어주는 메서드
int startflag = 0;
for (int i = 0; i < 6; i++) { // 5번포트까지 확인
cap[i] = VideoCapture(i);
if (cap[i].isOpened()) {
cout << "Opened Cam Port is : " << i << '\n';
CamNum++; // 연결된 카메라의 갯수 카운팅
startflag = 1;
}
}
if (startflag == 0) { // 연결 카메라가 없을경우
cout << "No camera connecetd" << '\n';
return;
}
}
void RunCam() {
for (int i = 0; i < 6; i++) {
if (cap[i].isOpened()) {
cap[i].read(image[i]);
imshow(Name[i], image[i]);
}
}
waitKey(1);
}
// 생성자
ControlCam() {
CheckCamPort();
cout << "=== 생성자 호출 : 연결된 카메라 대수 : " << CamNum << "===\n";
}
// 소멸자 -> 동적할당 해제용
~ControlCam() {
delete cap;
}
};
int main() {
ControlCam ctrl;
while (1) {
ctrl.RunCam();
}
return 0;
}
1. public, private, protected가 궁금하다면 여기를 참고
2. 배열을 동적할당 하는법 : int* something = new int[10]; 이런식 구체적으로 여기를 참고
+추가적으로 키보드 이벤트를 이용해 카메라 밝기 조절
////////////////////////////////////////////////////////////////
// importance : ☆☆☆☆☆
// title : 과제5
// 카메라를 control하기 위한 class를 선언하고 다음 기능을 구현하시오
// 1. 자동 카메라 연결(카메라의 개수를 입력 받음, (default = 1)
// 2. 연결된 카메라의 이미지 반환
// 3. 이미지의 밝기 변환
// date : 2020.02.05
// writer : jeong
// result : 카메라가 연결된 갯수만큼 창을 띄워서 동시에 카메라 영상을 틀어줌.
// 0,1,2,3,4,5 번 키를 누르면 각각의 카메라의 밝기를 조절할 수 있게됨.
// 방향키 위아래가 밝기 up, down
// 참고 :
////////////////////////////////////////////////////////////////
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
class ControlCam {
protected:
int CamNum = 0, CamNow = 0, InputKey, InitBrightness[6], flag = 0, temp[6] = { 0,0,0,0,0,0 };
VideoCapture* cap = new VideoCapture[6];
Mat* image = new Mat[6];
string Name[6] = { "camera 0","camera 1","camera 2", "camera 3", "camera 4", "camera 5" };
public:
void CheckCamPort() {// 카메라 열렸는지 확인하여 VideoCapture객체 만들어주는 메서드
int startflag = 0;
for (int i = 0; i < 6; i++) { // 5번포트까지 확인
cap[i] = VideoCapture(i);
if (cap[i].isOpened()) {
cout << "Opened Cam Port is : " << i << '\n';
startflag = 1;
InitBrightness[i] = cap[i].get(CAP_PROP_BRIGHTNESS); // 처음 밝기 저장
CamNum++;
}
}
if (startflag == 0) { // 연결 카메라가 없을경우
cout << "No camera connecetd" << '\n';
return;
}
}
int RunCam() { // 평소엔 0을 return, esc누르면 1을 return
for (int i = 0; i < 6; i++) {
if (cap[i].isOpened()) {
cap[i].read(image[i]);
imshow(Name[i], image[i]);
}
}
// 아래부터는 키보드 입력값에 따른 동작
InputKey = waitKeyEx(1);
switch (InputKey) {
case 32: // 스페이스바
cout << "정지\n";
while ((InputKey = waitKeyEx(1)) != 32); // 다시 스페이스바가 들어오길 기다린다.
cout << "재생\n"; // 들어온 값이 esc가 아니면 다시 재생
break;
case 48: // 숫자 0키
CamNow = 0;
cout << "0로 변경\n";
break;
case 49: // 숫자 1키
CamNow = 1;
cout << "1로 변경\n";
break;
case 50: // 숫자 2키
CamNow = 2;
cout << "2로 변경\n";
break;
case 51: // 숫자 3키
CamNow = 3;
cout << "3로 변경\n";
break;
case 52: // 숫자 4키
CamNow = 4;
cout << "4로 변경\n";
break;
case 53: // 숫자 5키
CamNow = 5;
cout << "5로 변경\n";
break;
case 2490368: // 위쪽방향키
cap[CamNow].set(CAP_PROP_BRIGHTNESS, InitBrightness[CamNow] + (++temp[CamNow]));
cout << "Up, Brightness : " << InitBrightness[CamNow] + (temp[CamNow]) << '\n';
break;
case 2621440: // 아랫쪽방향키
cap[CamNow].set(CAP_PROP_BRIGHTNESS, InitBrightness[CamNow] + (--temp[CamNow]));
cout << "Down, Brightness : " << InitBrightness[CamNow] + (temp[CamNow]) << '\n';
break;
case 27: // esc누르면
return 1;
}
return 0;
}
// 생성자
ControlCam() {
CheckCamPort();
cout << "=== 생성자 호출 : 연결된 카메라 대수 : " << CamNum << "===\n";
cout << "종료하고 싶으시면 esc키를 눌러주세요. 그래야 카메라 초기변수가 유지됩니다.\n";
}
// 소멸자 -> 동적할당 해제용
~ControlCam() {
for (int i = 0; i < 6; i++) { // 카메라 밝기 원래 초기값으로 다시 설정
cap[i].set(CAP_PROP_BRIGHTNESS, InitBrightness[i]);
}
delete cap;
}
};
int main() {
ControlCam ctrl;
while (1) {
if (ctrl.RunCam()) break; // esc키를 누르면 RunCam메서드가 1을 return하여 while 탈출
}
return 0;
}
1. 스페이스바 눌렀을 때 화면 정지하는법
while (1) {
int InputKey = waitKeyEx(1);
if (InputKey == 32) {
cout << "정지\n";
while ((InputKey = waitKeyEx(1)) != 32); // 다시 스페이스바가 들어오길 기다린다.
cout << "재생\n"; // 들어온 값이 esc가 아니면 다시 재생
break;
}
}
2. waitKey(), waitKeyEx()는 키보드 입력을 대기하는 함수로 0이면 key 입력이 있을때까지 무한대기. 특정 시간동안 대기를 하려면 ms값을 넣어주면 된다. 또한 ESC를 누를 경우 27을 리턴한다. 이런 리턴 값을 알면 버튼에 따라 다른 동작을 실시하도록 로직을 설계할 수 있다.
3. VideoCapture는 waitKey 또는 waitKeyEx를 while문 끝부분에 주지 않으면 실행되지 않는다.
아래의 소스에서 waitKey(1); 빼보시라. 회색화면만 나올뿐이다.
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main() {
VideoCapture cap = VideoCapture(0); // 0번 포트에 카메라가 연결되어 있으면 cap에 연결된다.
Mat image;
while (1) {
cap.read(image);
imshow("이미지", image);
waitKey(1);
}
return 0;
}
4. 방향키같은 특수한 키는 waitKey()를 사용하면 안되고, waitKeyEx를 사용해야 한다.
소스코드 궁금하신점이나, 비효율적인 부분 말씀해주시면 감사하겠습니다!!!
댓글