이번장에서 설명할 것은 실시간 object detection의 어마어마한 속도를 자랑하는 yolo다.

yolo란?
You only look once 의 줄임말로 어마어마하게 빠른시간으로 실시간 object detection 으로써, 엔비디아의 파스칼 타이탄X 그래픽카드(GPU) 기준으로 COCO 테스트 데이터에서 30FPS로 무료 mAP가 57.9%를 기록했다.
다른 디텍터랑 비교해보자면


위와 같이 엄청나게 빠른속도를 자랑하면서 정확도가 꽤 높은편이라는 걸 알수가 있다.
이제 YOLO( you only look once) 는 2015년 처음 나온 알고리즘으로 뉴럴넷 프레임워크 다크넷의 창시자 Joseph Redmon이라는 사람이 1저자로 참여한 알고리즘으로써 기존의 object detection이 region proposal을 1차적으로 수행 후, classification을 진행하던 방식에서 region proposal 단계를 아에 제거하고 한번에 object detection을 수행하는 구조를 가집니다.
이 욜로의 알고리즘에 대한 설명 자체는 Deepsystem이라는 분들의 프리젠테이션을 많이 참고했습니다
이 방식은, 입력이미지를 SxS 그리드 영역으로 나누고, 이 그리드영역에서 객체가 있을만한 영역에 해당하는 N개의 바운딩 박스를 예측한다음 해당 박스의 신뢰도(confidence) 를 계산합니다. 계산 방법은 해당 그리드에 객체가 있을 확률 Pr(Object)와 Ground Truth의 겹치는 영역의 비율을 나타내는 IOU를 곱해서 계산합니다.
그 다음 각각의 그리드마다 해당 클래스일 확률을 계산하는데 이 바운딩 박스와 classfication을 동시에 수행합니다.

이 joseph Redmon은 구글 넷(googlenet)의 아키텍쳐에서 영감으로 받았다고 하는데 inception 블럭 대신 단순한 converlution으로 네트워크를 구성했다고 나옵니다.

위의 도식표를 보면 알겠지만, 448x448로 된 3채널의 이미지를 입력받은 다음 Googlenet의 modification한 20개의 레이어는 고정한다음 마지막 4개의 레이어만 object detection 레이어에 맞게 학습을 시키는데

컨볼루션 레이어를 좀더 여기다가 더하면 좀더 좋은 결과를 가져오게 됩니다. 어쨋든 중요한것 마지막에 Reshape한 7x7의 그리드와 30개의 차원 벡터값을 가진 픽쳐맵인데 여기에 그리드별 바운드 박스와 confidence값 그리로 각 클래스별 예측값이 담겨져 있습니다.

30개의 차원 벡터안을 세부적으로 보자면, 5개씩 2개의 차원에는 각각 그리드의 좌표와 너비 높이 그리고 신뢰도값이 저장되고,

나머지 20개에 해당 인덱스가 특정 클래스일 확률값이들 들어가는데

이것을 어떻게 계산하나면 앞에 말한 곱셈 연산으로 계산되는데 즉 박스의 신뢰도와 이 20차원백터의 값을 곱하게 되면 특정클래스일 값이 되는 것입니다.

여기서 잠깐 집고 넘어가자면 앞에서 N개의 바운딩 박스를 예측한다고 이야기하는데 여기서 그 바운딩박스의 n개가 2개라서 2개의 박스만 하는것입니다.
따라서 이 연산을 반복하면 총 98개를 진행되는데

중복되는 것을 없애기 위해서 NMS(Non-Maximum Suppression) 알고리즘이라는걸 사용하게 됩니다.
이건 머 생각보다 간단한데 다음박스랑 비교해서 다음박스값이 더 작으면 그냥 0으로 치환해나갑니다.

그렇게 반복해 나가면 0으로 바뀐 값들이 많을텐데 그것을 이제 조건문으로 스킵할지 안할지 정하면 완료됩니다.

이제 위와 같은 실시간 object detection에서 혁신적으로 속도를 개선한 Yolo(you only look once)를 c# 프로그래밍으로 해봅시다.
우선 yolo자체가 다른 딥러닝 프레임워크와 마찬가지로 파이썬으로 기본적으로 되어있으므로, 래핑라이브러리인
AlturosDestination/Alturos.Yolo를 사용합니다. 위 프로젝트 donation들 감사합니다.
C# 프로그래밍 으로 구현하기

누겟패키지로 Alturos.yolo를 설치하고 다른 영상처리도 같이하기 위해 opencv sharp도 설치합니다.(카메라 연동 등등을 위해) opencv sharp 에 대해 잘 모르시는 분들은 전 장을 참고하시기 바랍니다.
실시간 영상을 테스트하기위해서는 꼭 쿠다연산을 사용하는게 좋습니다. Alturos.yolo는 엔비디아 쿠다 툴킷 10.2버젼과 cudnn7.6.5 버젼을 지원합니다.
두개다 설치한다음 cudnn64_7.dll파일을 꼭 프로젝트 실행폴더에 복사해놔야 에러가 안납니다.
또한 프로젝트 실행자체를 64비트 모드로 꼭 c# 딥러닝 라이브러리는 다들 64비트로 해야됩니다 32비트 안돌아갑니다.
benchmark참고해보면

속도차이가 10배에서 100배정도 나니 , 그냥 테스트 한번돌릴때는 cpu로 해도 되는데 실시간 영상하려면 꼭 GPU쓰셔야 되는거 아실겁니다.
pre-trained dataset을 사용하실려면 YOLOv2-tiny같은 경우는 누겟패키지에 Alturos.YoloV2TinyVocData패키지로 있으니 설치해서 쓰면 되고 다른것들은 직접 다운로드해서 쓰시던가 아래처럼 코드에 넣어서 자동으로 받게 해도 됩니다.

Alturos.YoloV2TinyVocData패키지를 설치해서 스면 yolov2-tiny로 그냥 오토매틱하게 쓰는데 다른걸 쓰려면 아래처럼 yoloWrapper() 선언할때 써줘야 된다.
using (var yoloWrapper = new YoloWrapper("yolov3.cfg", "yolov3.weights", "coco.names"))
{
}
설명은 yolov2tiny 버젼 기준으로 진행할 것이다.
우선 c# 프로그램에서 object detection 을 실시간을 하기 위해서 picturebox 1개 checkbox1개 timer 1개를 배치한다.

그 다음 라이브러리를 사용하게 using으로 선언한다음

노트북에서 실시간 영상을 가져오게 폼로딩때 videocapture로 영상을 가져온다

그 다음에 timer에 영상을 재생하는데 checkbox가 표시되면 object detection 을 하게 코딩을 한다.} } }
private void timer1_Tick(object sender, EventArgs e)
{
Mat frame = new Mat();
vc.Read(frame);
if (frame.Empty()) return;
else
{
try
{
this.Invoke((Action)(() =>
{
if (checkBoxSearch.Checked)
{
var cd = new YoloConfigurationDetector();
var config = cd.Detect();
using(var yoloWrap=new YoloWrapper(config))
{
var item=yoloWrap.Detect(frame.ToBytes());
foreach (var it in item)
{
int x = it.X;
int y = it.Y;
int w = it.Width;
int h = it.Height;
string kb = Convert.ToInt32(it.Confidence * 100).ToString() + "%";
int baseline = 0;
Rect rt = new Rect(x, y, w, h);
Scalar sc = new Scalar(0, 255, 0);
OpenCvSharp.Size sz = Cv2.GetTextSize(it.Type.ToString(), HersheyFonts.HersheyComplex, 1,1, out baseline);
OpenCvSharp.Point pt2 = new OpenCvSharp.Point(x + sz.Width, y);
OpenCvSharp.Point pt = new OpenCvSharp.Point(x, y);
Cv2.Rectangle(frame, rt, sc, 1);
Cv2.PutText(frame, it.Type.ToString(), pt, HersheyFonts.HersheyComplex, 1, sc);
Cv2.PutText(frame,kb , pt2, HersheyFonts.HersheyComplex, 1, sc);
}
}
pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(frame);
}
else
{
pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(frame);
}
}), null);
}
catch { }
}
}
위와 같이 코딩을 하게되면 이제 검사를 실시간으로 하게 된다.
위와 같이 진행하면 yolo를 다 한것이다 구체적으로 학습하고 응용은 다음장 진행하도록한다.
'C# 윈도우 프로그래밍' 카테고리의 다른 글
Geometric model finder C#(2) (0) | 2022.12.17 |
---|---|
Geometric model finder C#(1) (0) | 2022.12.17 |
Opencvsharp 탬플릿 매칭 c# (template Matching) opencv (0) | 2022.12.11 |
opencvsharp 실시간 마우스 처리 opencv c# (0) | 2022.12.11 |
opencvsharp 영상처리 프로그래밍(1) c# opencv (0) | 2022.12.11 |