안녕하세요 c++ 공부하고있는 대학생입니다.
이번에는 QT에서 MaskRCNN을 적용시키는 모습을 보여드리려구 합니다.
MaskRCNN 이란? 기존의 FastRCNN의 classification, localization 에 Mask branch가 추가된 것으로, 물체를 분별하고, 영역을 표시해주며, 해당 객체에 Mask를 씌워주는것 입니다.
저는 이미지에서 rectangle을 그린만큼의 이미지를 잘라서, 해당 이미지를 blob처리하여 객체를 판별하게 만들었습니다.
Rect cutrect(MaskX, MaskY, x - MaskX, y - MaskY);
Mat cutImage = frameGPU(cutrect);
blobFromImage(cutImage, blob, 1.0, Size(x - MaskX, y - MaskY), Scalar(), true, false);
net.setInput(blob);
std::vector<String> outNames(2);
outNames[0] = "detection_out_final";
outNames[1] = "detection_masks";
net.forward(outs, outNames);
outDetections = outs[0];
outMasks = outs[1];
MaskRCNNData.numDetections = outDetections.size[2];
MaskRCNNData.cnumClasses = outMasks.size[1];
outDetections = outDetections.reshape(1, outDetections.total() / 7);
일단 QT로 GUI를 구성해서 이미지를 불러오게 한 다음, Rect 함수로 x좌표 y 좌표, width, height 값을 잡아주었습니다.
원리는, x좌표 y좌표는 마우스 포인터에 클릭부분을 기준으로 하여 잡았고, width와 height 는 , rectangle을 그리기위해 y = x 대칭 점에 대해 잡아서 ,
width = LastX - FristX , heigh = LastY - FirstY 로 하였습니다.
혹시나 모를 예외처리때문에 각각 x좌표끼리, y좌표끼리 값을 비교하여 swap 사용자 정의함수를 만들어서 값을 바꿔주는 작업까지 처리하였습니다.
Rect box = Rect(MaskX, MaskY, x - MaskX + 1, y - MaskY + 1);
그런다음, 퍼센테이지를 나타내줄 label을 cv에 있는 format 함수를 이용해서 cv에있는 putText 함수로 이미지창에 표시를 해 주었습니다.
label = format("%.2f", score);
if (!classes.empty()) {
CV_Assert(MaskRCNNData.classId < (int)classes.size());
label = classes[MaskRCNNData.classId] + ":" + label;
}
int baseLine;
labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 1.5, 1, &baseLine);
box.y = max(box.y, labelSize.height);
rectangle(frameGPU, Point(MaskX, MaskY - round(0.5 * labelSize.height)), Point(MaskX + round(0.5* labelSize.width), MaskY + baseLine), Scalar(255, 255, 255), FILLED);
putText(frameGPU, label, Point(MaskX, MaskY), 3, 0.75, Scalar(0, 0, 0), 1);
이러한 과정을 통해서 결과를 보여드리면,
이렇게 나오게되고, 컬러부분을 보여드리면
color = colors[MaskRCNNData.classId % colors.size()];
resize(objectMask, objectMask, Size(box.width, box.height));
mask = (objectMask > maskThreshold);
coloredRoi = (0.5 * color + 0.7 * frameGPU(box));
coloredRoi.convertTo(coloredRoi, CV_8UC3);
findContours(mask, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
drawContours(frameGPU, contours, -1, color, 5, LINE_8, hierarchy, 100, Point(MaskX,MaskY));
coloredRoi.copyTo(frameGPU(box), mask);
핵심은, color 파일에 있는 color에 대한 정보를 가져오는 것 과, findContours 라는 관심있는 부분을 찾는 함수와, drawContours 라는 관심있는 부분을 draw 해 주는 부분입니다.