Я искал ответ везде, где мог, но не нашел.
Я делаю программу обнаружения комического воздушного шара, и мне нужно найти эллипс, который имеет определенный процент белого внутри контура (процент будет определен позже), поэтому мне нужно подсчитать белые пиксели внутри контура, и я не не знаю как.
Я пробовал countNonZero()
, но, поскольку параметр этого массива, он не принимает мои minEllipse[i]
или contours[i]
, которые объявлены как vector<RotatedRect>
.
Ниже приведен код:
// Modified version of thresold_callback function
// from http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/bounding_rotated_ellipses/bounding_rotated_ellipses.html
Mat fittingEllipse(int, void*, Mat inputImage)
{
Mat threshold_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
int numberOfCaptions = 0;
// Detect edges using Threshold
threshold(inputImage, threshold_output, 224, 250, THRESH_BINARY);
findContours(inputImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
vector<RotatedRect> minEllipse(contours.size());
Mat drawing = Mat::zeros(inputImage.size(), CV_8UC3);
for (int i = 0; i < contours.size(); i++)
{
if (contours[i].size() > 5)
minEllipse[i] = fitEllipse(Mat(contours[i]));
}
int totalContourSize = 0, whitepixels, blackpixels;
//Draw ellipse/caption
for (int i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(255, 0, 0);
if (minEllipse[i].size.height >= inputImage.rows / 8 && //IJIP-290-libre.pdf
minEllipse[i].size.width >= inputImage.cols / 10 && //IJIP-290-libre.pdf
minEllipse[i].size.height < inputImage.rows / 3 &&
minEllipse[i].size.width < inputImage.cols / 3 &&
(
(minEllipse[i].angle >= 0 && minEllipse[i].angle <= 10) ||
(minEllipse[i].angle >= 80 && minEllipse[i].angle <= 100) ||
(minEllipse[i].angle >= 170 && minEllipse[i].angle <= 190) ||
(minEllipse[i].angle >= 260 && minEllipse[i].angle <= 280) ||
(minEllipse[i].angle >= 350 && minEllipse[i].angle <= 360)
)) {
ellipse(drawing, minEllipse[i], color, -1, 8);
}
}
drawing = binarizeImage(drawing);
return drawing;
} // end of fittingEllipse
Mat CaptionDetection(Mat inputImage){
Mat outputImage, binaryImage, captionDetectImage;
binaryImage = captionDetectImage = binarizeImage(inputImage);
threshold(captionDetectImage, captionDetectImage, 224, 250, 0); //IJIP-290-libre.pdf
GaussianBlur(captionDetectImage, captionDetectImage, Size(9, 9), 0, 0);
captionDetectImage = fittingEllipse(0, 0, captionDetectImage);
//binaryImage = invertImage(binaryImage);
outputImage = inputImage;
for (int i = 0; i < inputImage.rows; i++) {
for (int j = 0; j < inputImage.cols; j++) {
if (captionDetectImage.at<uchar>(i, j) == 0) {
outputImage.at<Vec3b>(i, j)[0] = outputImage.at<Vec3b>(i, j)[1] = outputImage.at<Vec3b>(i, j)[2] = 0;
}
}
}
return outputImage;
} // end of CaptionDetection
Очень громоздкий оператор if дает мне только 53% точности обнаружения комического воздушного шара (не говоря уже обо всех ложных обнаружениях), поэтому мне нужно получить процент белых пикселей в найденных контурах, чтобы получить более высокий процент.
ИЗМЕНИТЬ:
Я бы хотел, чтобы вся страница манги была черной, кроме комических воздушных шаров, а затем подсчитывалось количество белых и черных пикселей.
ТОЛЬКО в функции CaptionDetection
я должен подсчитывать количество пикселей для каждой подписи
ЗАКЛЮЧИТЕЛЬНЫЙ ОТВЕТ
Я отредактировал код, который дал пользователь Kornel
Mat fittingEllipse(int, void*, Mat inputImage)
{
Mat outputImage;
vector<Vec4i> hierarchy;
int numberOfCaptions = 0;
// Detect edges using Threshold
threshold(inputImage, inputImage, 224, 250, THRESH_BINARY);
findContours(inputImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
vector<RotatedRect> minEllipse(contours.size());
for (int i = 0; i < contours.size(); i++)
{
if (contours[i].size() > 5)
minEllipse[i] = fitEllipse(Mat(contours[i]));
}
//Draw ellipse/caption
outputImage = Mat::zeros(inputImage.size(), CV_8UC3);
for (int i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(255, 255, 255);
Mat drawing = Mat::zeros(inputImage.size(), CV_8UC3);
ellipse(drawing, minEllipse[i], color, -1, 8);
drawing = binarizeImage(drawing);
int area = countNonZero(drawing);
if ((area >= 10000 && area <= 40000) &&
(
(minEllipse[i].angle >= 0 && minEllipse[i].angle <= 10) ||
(minEllipse[i].angle >= 80 && minEllipse[i].angle <= 100) ||
(minEllipse[i].angle >= 170 && minEllipse[i].angle <= 190) ||
(minEllipse[i].angle >= 260 && minEllipse[i].angle <= 280) ||
(minEllipse[i].angle >= 350 && minEllipse[i].angle <= 360)
)){
ellipse(outputImage, minEllipse[i], color, -1, 8);
captionMask[captionCount] = drawing;
captionCount++;
}
}
imwrite((string)SAVE_FILE_DEST + "out.jpg", outputImage);
return outputImage;
} // end of fittingEllipse
Mat replaceROIWithOrigImage(Mat inputImg, Mat mask, int k){
Mat outputImage = inputImg;
Mat maskImg = mask;
imwrite((string)SAVE_FILE_DEST + "inputbefore[" + to_string(k) + "].jpg", inputImg);
for (int i = 0; i < inputImg.rows; i++) {
for (int j = 0; j < inputImg.cols; j++) {
if (maskImg.at<uchar>(i, j) == 0) {
inputImg.at<Vec3b>(i, j)[0] = inputImg.at<Vec3b>(i, j)[1] = inputImg.at<Vec3b>(i, j)[2] = 0;
}
}
}
imwrite((string)SAVE_FILE_DEST + "maskafter[" + to_string(k) + "].jpg", inputImg);
return inputImg;
}
Mat CaptionDetection(Mat inputImage){
Mat outputImage, binaryImage, captionDetectImage;
binaryImage = captionDetectImage = binarizeImage(inputImage);
threshold(captionDetectImage, captionDetectImage, 224, 250, 0); //IJIP-290-libre.pdf
GaussianBlur(captionDetectImage, captionDetectImage, Size(9, 9), 0, 0);
captionDetectImage = fittingEllipse(0, 0, captionDetectImage);
for (int i = 0; i < captionCount; i++){
Mat replacedImg = replaceROIWithOrigImage(inputImage.clone(), captionMask[i], i);
int area = countNonZero(binarizeImage(replacedImg));
cout << area << endl;
}
return outputImage;
} // end of CaptionDetection
Условие if в fittingEllipse()
должно быть позже отредактировано для большей точности.
Спасибо за помощь и время пользователям a-Jays и Kornel!
sourceImg.copyTo( destImage, maskImg )
. - person a-Jays   schedule 26.03.2015