私は、iPhoneのカメラを使ってテレビ画面を検出しています。現在のアプローチは、ピクセルごとに後続のフレームを比較し、累積差を追跡することです。結果は画像に示されているように2値画像です。 カメラを使ったOpenCV検出画面
私にとっては、これは長方形のように見えますが、OpenCVではそうは思われません。その側面は完全に真っ直ぐではなく、時には検出を困難にするためにさらに色のにじみがあります。 OpenCVに慣れていないので、矩形を検出しようとしているOpenCVコードです。
uint32_t *ptr = (uint32_t*)CVPixelBufferGetBaseAddress(buffer);
cv::Mat image((int)width, (int)height, CV_8UC4, ptr); // unsigned 8-bit values for 4 channels (ARGB)
cv::Mat image2 = [self matFromPixelBuffer:buffer];
std::vector<std::vector<cv::Point>>squares;
// blur will enhance edge detection
cv::Mat blurred(image2);
GaussianBlur(image2, blurred, cvSize(3,3), 0);//change from median blur to gaussian for more accuracy of square detection
cv::Mat gray0(blurred.size(), CV_8U), gray;
std::vector<std::vector<cv::Point> > contours;
// find squares in every color plane of the image
for (int c = 0; c < 3; c++) {
int ch[] = {c, 0};
mixChannels(&blurred, 1, &gray0, 1, ch, 1);
// try several threshold levels
const int threshold_level = 2;
for (int l = 0; l < threshold_level; l++) {
// Use Canny instead of zero threshold level!
// Canny helps to catch squares with gradient shading
if (l == 0) {
Canny(gray0, gray, 10, 20, 3); //
// Dilate helps to remove potential holes between edge segments
dilate(gray, gray, cv::Mat(), cv::Point(-1,-1));
} else {
gray = gray0 >= (l+1) * 255/threshold_level;
}
// Find contours and store them in a list
findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
// Test contours
std::vector<cv::Point> approx;
int biggestSize = 0;
for (size_t i = 0; i < contours.size(); i++) {
// approximate contour with accuracy proportional
// to the contour perimeter
approxPolyDP(cv::Mat(contours[i]), approx, arcLength(cv::Mat(contours[i]), true)*0.02, true);
if (approx.size() != 4)
continue;
// Note: absolute value of an area is used because
// area may be positive or negative - in accordance with the
// contour orientation
int areaSize = fabs(contourArea(cv::Mat(approx)));
if (approx.size() == 4 && areaSize > biggestSize)
biggestSize = areaSize;
cv::RotatedRect boundingRect = cv::minAreaRect(approx);
float aspectRatio = boundingRect.size.width/boundingRect.size.height;
cv::Rect boundingRect2 = cv::boundingRect(approx);
float aspectRatio2 = (float)boundingRect2.width/(float)boundingRect2.height;
bool convex = isContourConvex(cv::Mat(approx));
if (approx.size() == 4 &&
fabs(contourArea(cv::Mat(approx))) > minArea &&
(aspectRatio >= minAspectRatio && aspectRatio <= maxAspectRatio) &&
isContourConvex(cv::Mat(approx))) {
double maxCosine = 0;
for (int j = 2; j < 5; j++) {
double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
maxCosine = MAXIMUM(maxCosine, cosine);
}
double area = fabs(contourArea(cv::Mat(approx)));
if (maxCosine < 0.3) {
squares.push_back(approx);
}
}
}
}
はキャニー・ステップの後の画像は、それは私には罰金だが、何らかの理由矩形のために検出されないこの のように見えます。私のパラメータに間違ったことがあれば誰でも説明できますか?
私の2番目のアプローチは、基本的に上記と同じコードを使用してOpenCV Houghライン検出を使用することでした。Canny画像に対しては、次にHoughLines関数を呼び出します。私は垂直線を検出するためにしきい値を低くしなければならないので、私にはかなりの数の線があります。結果の行はこのようなものです:
問題は、いくつかの多くの行があるということです。最初の画像に示されているように、青い矩形の辺に接触している線を見つけるにはどうすればよいですか?
また、画面を検出する優れた方法はありますか?
返信ありがとう、非常に巧妙なアプローチ。これを実装しましたが、結果として得られる長方形が大きすぎます。色のにじみがあるすべての領域が含まれます。私はコーナーを正確に検出する必要があります。 – superg