如何识别照片中的形状?我想用iOS应用程序实现它,但目前唯一被认可的是填充的红色方块。
我在iOS 8上使用OpenCV版本2.4.9。
// Convert to grayscale
cv::Mat gray;
cv::cvtColor(src, gray, CV_BGR2GRAY);
// Convert to binary image using Canny
cv::Mat bw;
cv::Canny(gray, bw, 0, 50, 5);
imageView.image = [UIImage fromCVMat:gray];
// Find contours
std::vector<std::vector<cv::Point> > contours;
cv::findContours(bw.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
// The array for storing the approximation curve
std::vector<cv::Point> approx;
// We'll put the labels in this destination image
cv::Mat dst = src.clone();
for (int i = 0; i < contours.size(); i++)
{
// Approximate contour with accuracy proportional
// to the contour perimeter
cv::approxPolyDP(
cv::Mat(contours[i]),
approx,
cv::arcLength(cv::Mat(contours[i]), true) * 0.02,
true
);
BOOL area = std::fabs(cv::contourArea(contours[i])) < 10;
BOOL convex = false; // !cv::isContourConvex(approx);
// Skip small or non-convex objects
if (area || convex) {
if (area) {
NSLog(@"contourarea : %f", std::fabs(cv::contourArea(contours[i])));
} else {
NSLog(@"convex : %i", !cv::isContourConvex(approx));
}
NSLog(@"=========");
continue;
}
if (approx.size() == 1) {
setLabel(dst, "TRI", contours[i]); // Triangles
} else if (approx.size() >= 4 && approx.size() <= 6) {
// Number of vertices of polygonal curve
int vtc = approx.size();
// Get the degree (in cosines) of all corners
std::vector<double> cos;
for (int j = 2; j < vtc+1; j++) {
cos.push_back(angle(approx[j%vtc], approx[j-2], approx[j-1]));
}
// Sort ascending the corner degree values
std::sort(cos.begin(), cos.end());
// Get the lowest and the highest degree
double mincos = cos.front();
double maxcos = cos.back();
// Use the degrees obtained above and the number of vertices
// to determine the shape of the contour
if (vtc == 4 && mincos >= -0.1 && maxcos <= 0.3)
{
// Detect rectangle or square
cv::Rect r = cv::boundingRect(contours[i]);
double ratio = std::abs(1 - (double)r.width / r.height);
setLabel(dst, ratio <= 0.02 ? "SQU" : "RECT", contours[i]);
}
else if (vtc == 5 && mincos >= -0.34 && maxcos <= -0.27)
setLabel(dst, "PENTA", contours[i]);
else if (vtc == 6 && mincos >= -0.55 && maxcos <= -0.45)
setLabel(dst, "HEXA", contours[i]);
}
else
{
// Detect and label circles
double area = cv::contourArea(contours[i]);
cv::Rect r = cv::boundingRect(contours[i]);
int radius = r.width / 2;
if (std::abs(1 - ((double)r.width / r.height)) <= 0.2 &&
std::abs(1 - (area / (CV_PI * std::pow(radius, 2)))) <= 0.2) {
}
}
} // end of for() loop