問(wèn)題描述
我正在使用 OpenCV 庫(kù)示例中提供的程序 squares.c.它適用于每個(gè)圖像,但我真的不明白為什么它不能識(shí)別該圖像中繪制的正方形
DILATE 之后:
RESULT 圖像(紅色)http://img267.imageshack.us/img267/8016/resultuq.jpg
如您所見(jiàn),未檢測(cè)到正方形.
檢測(cè)后我需要提取正方形中包含的區(qū)域......沒(méi)有ROI怎么可能?
下面的源代碼展示了 Square Detector 程序的一個(gè)小變化.它并不完美,但它說(shuō)明了解決您的問(wèn)題的一種方法.
您可以將此代碼與原始代碼進(jìn)行比較并檢查所做的所有更改,但主要的更改是:
將閾值級(jí)別的數(shù)量減少到 2.
在
findSquares()
的開(kāi)頭,擴(kuò)大圖像檢測(cè)細(xì)小的白色方塊,然后模糊整個(gè)圖像,因此算法不會(huì)將大海和天空檢測(cè)為單個(gè)方塊.
編譯后,使用以下語(yǔ)法運(yùn)行應(yīng)用程序:./app
//平方檢測(cè)器"程序.//它順序加載多個(gè)圖像并嘗試在其中找到正方形//每張圖片#include "highgui.h"#include "cv.h"#include #include <math.h>#include 使用命名空間 cv;使用命名空間標(biāo)準(zhǔn);無(wú)效的幫助(){cout<<"
一個(gè)使用金字塔縮放、Canny、輪廓、輪廓簡(jiǎn)化和
的程序"內(nèi)存存儲(chǔ)(所有人都可以找到)
""圖像列表中的方塊 pic1-6.png
""返回在圖像上檢測(cè)到的正方形序列.
""序列存儲(chǔ)在指定的內(nèi)存中
"呼叫:
""./平方
""使用 OpenCV 版本 %s
" <<CV_VERSION <<"
" <<結(jié)束;}整數(shù)閾值 = 50,N = 2;//karlphillip:將 N 減少到 2,是 11.const char* wndname = "平方檢測(cè)演示";//輔助函數(shù)://找到向量之間夾角的余弦值//從 pt0->pt1 和從 pt0->pt2雙角(點(diǎn)pt1,點(diǎn)pt2,點(diǎn)pt0){雙 dx1 = pt1.x - pt0.x;雙 dy1 = pt1.y - pt0.y;雙 dx2 = pt2.x - pt0.x;雙 dy2 = pt2.y - pt0.y;返回 (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);}//返回在圖像上檢測(cè)到的正方形序列.//序列存儲(chǔ)在指定的內(nèi)存中void findSquares( const Mat& image, vector<vector<Point> >& squares ){squares.clear();Mat pyr, timg, gray0(image.size(), CV_8U), gray;//karlphillip: 擴(kuò)大圖像,以便此技術(shù)可以檢測(cè)白色方塊,墊出(圖像);擴(kuò)張(出,出,墊(),點(diǎn)(-1,-1));//然后模糊它,使海洋/大海成為一大段,以避免將它們檢測(cè)為 2 個(gè)大方塊.中值模糊(出,出,7);//縮小和放大圖像以濾除噪聲pyrDown(out, pyr, Size(out.cols/2, out.rows/2));pyrUp(pyr, timg, out.size());矢量<矢量<點(diǎn)>>輪廓;//在圖像的每個(gè)顏色平面中找到正方形for( int c = 0; c <3; c++ ){int ch[] = {c, 0};mixChannels(&timg, 1, &gray0, 1, ch, 1);//嘗試幾個(gè)閾值級(jí)別for( int l = 0; l = (l+1)*255/N;}//找到輪廓并將它們?nèi)看鎯?chǔ)為列表findContours(灰色,輪廓,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);矢量<點(diǎn)>約;//測(cè)試每個(gè)輪廓for( size_t i = 0; i 1000 & &isContourConvex(Mat(approx)) ){雙最大余弦 = 0;for( int j = 2; j <5; j++ ){//找到關(guān)節(jié)邊緣之間夾角的最大余弦值雙余弦 = fabs(angle(approx[j%4],approx[j-2],approx[j-1]));maxCosine = MAX(maxCosine, cosine);}//如果所有角度的余弦都很小//(所有角度都是~90度)然后寫(xiě)quandrange//頂點(diǎn)到結(jié)果序列如果(最大余弦<0.3)squares.push_back(大約);}}}}}//該函數(shù)繪制圖像中的所有方塊void drawSquares( Mat& image, const vector<vector<Point> >& squares ){for( size_t i = 0; i < squares.size(); i++ ){const Point* p = &squares[i][0];int n = (int)squares[i].size();polylines(image, &p, &n, 1, true, Scalar(0,255,0), 3, CV_AA);}imshow(wndname,圖像);}int main(int argc, char** argv){如果 (argc <2){cout<<用法:./program <文件>"<<結(jié)束;返回-1;}//static const char* names[] = { "pic1.png", "pic2.png", "pic3.png",//"pic4.png", "pic5.png", "pic6.png", 0 };靜態(tài)常量字符*名稱(chēng)[] = { argv[1], 0 };幫助();命名窗口( wndname, 1 );矢量<矢量<點(diǎn)>>正方形;for( int i = 0; names[i] != 0; i++ ){Mat image = imread(names[i], 1);如果(圖像.空()){cout<<無(wú)法加載" <<名稱(chēng)[i] <<結(jié)束;繼續(xù);}findSquares(圖像,正方形);drawSquares(圖像,正方形);imwrite("out.jpg", image);int c = waitKey();如果((字符)c == 27 )休息;}返回0;}
輸出:
I'm using the program squares.c available in the samples of OpenCV libraries. It works well with every image, but I really can't figure it out why it doesn't recognize the square drawn in that image
http://desmond.imageshack.us/Himg12/scaled.php?server=12&filename=26725680.jpg&res=medium
After CANNY:
After DILATE:
The RESULT image (in red) http://img267.imageshack.us/img267/8016/resultuq.jpg
As you can see, the square is NOT detected.
After the detection I need to extract the area contained in the square...How is it possible without a ROI?
The source code below presents a small variation of the Square Detector program. It's not perfect, but it illustrates one way to approach your problem.
You can diff this code to the original and check all the changes that were made, but the main ones are:
Decrease the number of threshold levels to 2.
In the beginning of
findSquares()
, dilate the image to detect the thin white square, and then blur the entire image so the algorithm doesn't detect the sea and the sky as individual squares.
Once compiled, run the application with the following syntax: ./app <image>
// The "Square Detector" program.
// It loads several images sequentially and tries to find squares in
// each image
#include "highgui.h"
#include "cv.h"
#include <iostream>
#include <math.h>
#include <string.h>
using namespace cv;
using namespace std;
void help()
{
cout <<
"
A program using pyramid scaling, Canny, contours, contour simpification and
"
"memory storage (it's got it all folks) to find
"
"squares in a list of images pic1-6.png
"
"Returns sequence of squares detected on the image.
"
"the sequence is stored in the specified memory storage
"
"Call:
"
"./squares
"
"Using OpenCV version %s
" << CV_VERSION << "
" << endl;
}
int thresh = 50, N = 2; // karlphillip: decreased N to 2, was 11.
const char* wndname = "Square Detection Demo";
// helper function:
// finds a cosine of angle between vectors
// from pt0->pt1 and from pt0->pt2
double angle( Point pt1, Point pt2, Point pt0 )
{
double dx1 = pt1.x - pt0.x;
double dy1 = pt1.y - pt0.y;
double dx2 = pt2.x - pt0.x;
double dy2 = pt2.y - pt0.y;
return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}
// returns sequence of squares detected on the image.
// the sequence is stored in the specified memory storage
void findSquares( const Mat& image, vector<vector<Point> >& squares )
{
squares.clear();
Mat pyr, timg, gray0(image.size(), CV_8U), gray;
// karlphillip: dilate the image so this technique can detect the white square,
Mat out(image);
dilate(out, out, Mat(), Point(-1,-1));
// then blur it so that the ocean/sea become one big segment to avoid detecting them as 2 big squares.
medianBlur(out, out, 7);
// down-scale and upscale the image to filter out the noise
pyrDown(out, pyr, Size(out.cols/2, out.rows/2));
pyrUp(pyr, timg, out.size());
vector<vector<Point> > contours;
// find squares in every color plane of the image
for( int c = 0; c < 3; c++ )
{
int ch[] = {c, 0};
mixChannels(&timg, 1, &gray0, 1, ch, 1);
// try several threshold levels
for( int l = 0; l < N; l++ )
{
// hack: use Canny instead of zero threshold level.
// Canny helps to catch squares with gradient shading
if( l == 0 )
{
// apply Canny. Take the upper threshold from slider
// and set the lower to 0 (which forces edges merging)
Canny(gray0, gray, 0, thresh, 5);
// dilate canny output to remove potential
// holes between edge segments
dilate(gray, gray, Mat(), Point(-1,-1));
}
else
{
// apply threshold if l!=0:
// tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
gray = gray0 >= (l+1)*255/N;
}
// find contours and store them all as a list
findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
vector<Point> approx;
// test each contour
for( size_t i = 0; i < contours.size(); i++ )
{
// approximate contour with accuracy proportional
// to the contour perimeter
approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);
// square contours should have 4 vertices after approximation
// relatively large area (to filter out noisy contours)
// and be convex.
// Note: absolute value of an area is used because
// area may be positive or negative - in accordance with the
// contour orientation
if( approx.size() == 4 &&
fabs(contourArea(Mat(approx))) > 1000 &&
isContourConvex(Mat(approx)) )
{
double maxCosine = 0;
for( int j = 2; j < 5; j++ )
{
// find the maximum cosine of the angle between joint edges
double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
maxCosine = MAX(maxCosine, cosine);
}
// if cosines of all angles are small
// (all angles are ~90 degree) then write quandrange
// vertices to resultant sequence
if( maxCosine < 0.3 )
squares.push_back(approx);
}
}
}
}
}
// the function draws all the squares in the image
void drawSquares( Mat& image, const vector<vector<Point> >& squares )
{
for( size_t i = 0; i < squares.size(); i++ )
{
const Point* p = &squares[i][0];
int n = (int)squares[i].size();
polylines(image, &p, &n, 1, true, Scalar(0,255,0), 3, CV_AA);
}
imshow(wndname, image);
}
int main(int argc, char** argv)
{
if (argc < 2)
{
cout << "Usage: ./program <file>" << endl;
return -1;
}
// static const char* names[] = { "pic1.png", "pic2.png", "pic3.png",
// "pic4.png", "pic5.png", "pic6.png", 0 };
static const char* names[] = { argv[1], 0 };
help();
namedWindow( wndname, 1 );
vector<vector<Point> > squares;
for( int i = 0; names[i] != 0; i++ )
{
Mat image = imread(names[i], 1);
if( image.empty() )
{
cout << "Couldn't load " << names[i] << endl;
continue;
}
findSquares(image, squares);
drawSquares(image, squares);
imwrite("out.jpg", image);
int c = waitKey();
if( (char)c == 27 )
break;
}
return 0;
}
Outputs:
這篇關(guān)于正方形檢測(cè)沒(méi)有找到正方形的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!