Skip to content

Commit ea9b8fe

Browse files
author
Win32 Desktop
committed
Updated the Method for Mark Point Detection
1 parent 0927441 commit ea9b8fe

16 files changed

+583
-458
lines changed

Duke/cameracalibration.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,8 @@ int CameraCalibration::calibrateCamera()
263263
cv::vector<cv::Mat> camRotationVectors;
264264
cv::vector<cv::Mat> camTranslationVectors;
265265

266-
rms = cv::calibrateCamera(objBoardCornersCam, imgBoardCornersCam, camImageSize, camMatrix, distortion, camRotationVectors,camTranslationVectors,0,
267-
cv::TermCriteria( (cv::TermCriteria::COUNT)+(cv::TermCriteria::EPS), 30, DBL_EPSILON) );
268-
//rms = cv::calibrateCamera(objBoardCornersCam, imgBoardCornersCam, camImageSize, camMatrix,
269-
//distortion, camRotationVectors, camTranslationVectors, CV_CALIB_FIX_K4|CV_CALIB_FIX_K5);
266+
rms = cv::calibrateCamera(objBoardCornersCam, imgBoardCornersCam, camImageSize, camMatrix, distortion, camRotationVectors,camTranslationVectors,0);
267+
//rms = cv::calibrateCamera(objBoardCornersCam, imgBoardCornersCam, camImageSize, camMatrix,distortion, camRotationVectors, camTranslationVectors, CV_CALIB_FIX_K4|CV_CALIB_FIX_K5);
270268
if(isleft){
271269
undistortCameraImgPoints(findFunLeft,findFunLeft);
272270
camMatrixL = camMatrix;

Duke/dotmatch.cpp

+85-11
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ bool cameraLoaded = false;
55
int YDISTANCE = 4;//两相机标志点Y向距离小于该值认为是同一点
66
int EDGEUP = 10;//水平方向上标志点边缘黑色宽度上限
77
int EDGEDOWN = 0;
8-
int MIDDOWN = 8;
9-
int MIDUP = 40;
8+
int MIDDOWN = 2;
9+
int MIDUP = 30;
1010
float EPIPOLARERROR = 0.1;//特征点匹配时极线误差上界
1111
float tolerance = 2;//判断特征值是否相等时的误差
1212

@@ -59,8 +59,36 @@ vector<vector<float>> DotMatch::findDot(Mat &image, bool isleft)
5959
adaptiveThreshold(image,bimage,255,ADAPTIVE_THRESH_MEAN_C,THRESH_BINARY,blocksize,60);
6060
//blocksize较大可以使处理效果趋向二值化,较小则趋向边缘提取;C值的作用在于抑制噪声
6161
#else
62-
bwThreshold = OSTU_Region(image);
63-
bimage = image >= bwThreshold;
62+
Mat temp = Mat::zeros(image.size(),CV_8U);
63+
Mat mask = Mat::zeros(image.size(),CV_8U);
64+
int T1 = OSTU_Region(image);
65+
for (size_t i = 0; i < image.rows; i++){
66+
uchar *data = image.ptr<uchar>(i);
67+
for (int j = 0;j < image.cols;j++){
68+
if (data[j] >= T1){
69+
bimage.at<uchar>(i,j)=255;
70+
temp.at<uchar>(i,j) = T1;
71+
}
72+
else{
73+
temp.at<uchar>(i,j)=data[j];
74+
mask.at<uchar>(i,j)=255;
75+
}
76+
}
77+
}
78+
Mat element = getStructuringElement(MORPH_ELLIPSE, Size(11, 11));
79+
morphologyEx(mask,mask,MORPH_OPEN,element);
80+
//cvNamedWindow("1",WINDOW_NORMAL);
81+
//imshow("1", mask);
82+
int T2 = OSTU_Region(temp);
83+
for (size_t i = 0; i < temp.rows; i++){
84+
uchar *data = temp.ptr<uchar>(i);
85+
for (int j = 0;j < temp.cols;j++){
86+
if (data[j] >= T2){
87+
if (mask.at<uchar>(i,j)>0)
88+
bimage.at<uchar>(i,j)=255;
89+
}
90+
}
91+
}
6492
#endif
6593

6694
#ifdef DEBUG
@@ -138,7 +166,7 @@ vector<vector<float>> DotMatch::findDot(Mat &image, bool isleft)
138166
cvWaitKey();
139167
#endif
140168

141-
vector<Point2f> out = subPixel(bimage, alltemp);//将初步得到的圆心坐标进一步精确
169+
vector<Point2f> out = subPixel(bimage, alltemp);//make the coordinate of circle center more accurate
142170

143171
#ifdef DEBUG
144172
for (size_t i=0; i <out.size();i++)
@@ -1397,27 +1425,71 @@ vector<Point2f> DotMatch::subPixel(Mat img, vector<vector<float>> vec)
13971425
for (size_t i = 0; i < vec.size(); i++){
13981426
p.x = (int)(vec[i][1] + vec[i][2])/2;
13991427
p.y = (int)vec[i][0];
1428+
1429+
///Till now, the center coordinate has been calculated, the next step select an ROI around the center and perform a
1430+
/// ellipse fitting using OpenCV
1431+
Mat square = img(Rect(p.x-MIDUP,p.y-MIDUP,2*MIDUP,2*MIDUP));
1432+
/*
1433+
///If the amount of black pixels in square beyond threshold, continue
1434+
int black = 0;
1435+
for (int r=0;r<square.rows;r++){
1436+
uchar* pix = square.ptr<uchar>(r);
1437+
for (int c=0;c<square.cols;c++){
1438+
if (pix[c] == 0)
1439+
black++;
1440+
}
1441+
}
1442+
if (black>450)//half of the square area
1443+
continue;
1444+
*/
1445+
vector<Point2f> centers;
1446+
vector<vector<Point> > contours;
1447+
findContours(square, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
1448+
if (contours.size() > 4)
1449+
continue;
1450+
for(size_t i = 0; i < contours.size()-1; i=i+2){
1451+
size_t count = contours[i].size();
1452+
if( count < 16 )//如果该轮廓中所包含的点不足16个,则忽略
1453+
continue;
1454+
Mat pointsf;
1455+
Mat(contours[i]).convertTo(pointsf, CV_32F);
1456+
RotatedRect box = fitEllipse(pointsf);
1457+
if( MAX(box.size.width, box.size.height) > MIN(box.size.width, box.size.height)*5 )
1458+
continue;
1459+
if(box.size.width <= 2 || box.size.height <= 2)
1460+
continue;
1461+
if(box.size.width > MIDUP || box.size.height > MIDUP)
1462+
continue;
1463+
box.center.x = box.center.x+p.x-MIDUP;
1464+
box.center.y = box.center.y+p.y-MIDUP;
1465+
centers.push_back(box.center);
1466+
}
1467+
if (!centers.empty()){
1468+
p.x = centers[0].x;
1469+
p.y = centers[0].y;
1470+
}
1471+
14001472
int xl = 0;
14011473
int xr = 0;
14021474
int yu = 0;
14031475
int yd = 0;
1404-
if (img.at<uchar>(p.y, p.x) != 0){
1405-
while (img.at<uchar>(p.y, (p.x - xl)) > 0){
1476+
if (img.at<uchar>((int)p.y, (int)p.x) != 0){
1477+
while (img.at<uchar>((int)p.y, ((int)p.x - xl)) > 0){
14061478
xl++;
14071479
if (xl > MIDUP || (p.x - xl) <= 0)
14081480
break;
14091481
}
1410-
while (img.at<uchar>(p.y, (p.x + xr)) > 0){
1482+
while (img.at<uchar>((int)p.y, ((int)p.x + xr)) > 0){
14111483
xr++;
14121484
if (xr > MIDUP || (p.x + xr) >= img.cols)
14131485
break;
14141486
}
1415-
while (img.at<uchar>((p.y + yu), p.x) > 0){
1487+
while (img.at<uchar>(((int)p.y + yu), (int)p.x) > 0){
14161488
yu++;
14171489
if (yu > MIDUP || (p.y + yu) >= img.rows)
14181490
break;
14191491
}
1420-
while (img.at<uchar>((p.y - yd), p.x) > 0){
1492+
while (img.at<uchar>(((int)p.y - yd), (int)p.x) > 0){
14211493
yd++;
14221494
if (yd > MIDUP || (p.y - yd) <= 0)
14231495
break;
@@ -1431,6 +1503,7 @@ vector<Point2f> DotMatch::subPixel(Mat img, vector<vector<float>> vec)
14311503
continue;
14321504
}
14331505
else{
1506+
/*
14341507
if (yu >= yd)
14351508
p.y = p.y + (yu-yd)/2;
14361509
else
@@ -1439,7 +1512,8 @@ vector<Point2f> DotMatch::subPixel(Mat img, vector<vector<float>> vec)
14391512
p.x = p.x - (xl-xr)/2;
14401513
else
14411514
p.x = p.x + (xr - xl)/2;
1442-
out.push_back(p);
1515+
*/
1516+
out.push_back(p);
14431517
}
14441518
}
14451519
}

Duke/dotmatch.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
//调试用宏定义
55
//#define DEBUG
6-
#define USE_ADAPTIVE_THRESHOLD
6+
//#define USE_ADAPTIVE_THRESHOLD
77
#define USE_FOUR_POINT
88
//#define TEST_SURF
99

Duke/graycodes.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ void GrayCodes::generateGrays()
109109
}
110110
}
111111
}
112+
///保存格雷码
113+
//saveGray();
112114
}
113115

114116
int GrayCodes::grayToDec(cv::vector<bool> gray)//convert a gray code sequence to a decimal number
@@ -124,3 +126,13 @@ int GrayCodes::grayToDec(cv::vector<bool> gray)//convert a gray code sequence to
124126
}
125127
return dec;
126128
}
129+
130+
void GrayCodes::saveGray()
131+
{
132+
if (useEpi){
133+
for (size_t i = 0; i<2+2*numOfColImgs;i++){
134+
QString f = projectPath + "/" + QString::number(i) + ".png";
135+
cv::imwrite(f.toStdString(),grayCodes[i]);
136+
}
137+
}
138+
}

Duke/graycodes.h

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class GrayCodes
1818
~GrayCodes();
1919

2020
cv::Mat grayCodes[GRAY_MAX_NUM];
21+
QString projectPath;
2122
bool useEpi;//是否应用极线校正
2223

2324
int getNumOfImgs();
@@ -32,6 +33,7 @@ class GrayCodes
3233

3334
void calNumOfImgs();
3435
void allocMemForImgs();
36+
void saveGray();
3537

3638
bool imgsLoaded;
3739
int numOfImgs;

Duke/mainwindow.cpp

+19-18
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,20 @@ MainWindow::MainWindow(QWidget *parent)
2424
: QMainWindow(parent),
2525
ui(new Ui::MainWindow)
2626
{
27-
/*****生成主窗口UI*****/
27+
///---------生成主窗口UI----------/
2828
ui->setupUi(this);
2929

30-
/*****声明全局变量*****/
30+
///--------声明全局变量-----------/
3131
saveCount = 1;//Save calib images start with 1
3232
scanSN = -1;
3333
isConfigured = false;
3434
isProjectorOpened = true;
3535

36-
/****生成计时器并连接*****/
36+
///-----------------生成计时器并连接--------------------/
3737
timer = new QTimer(this);
3838
connect(timer, SIGNAL(timeout()), this, SLOT(readframe()));
3939

40-
/****声明相机****/
40+
///---------声明相机-----------/
4141
usebc = false;
4242
DHC = new DaHengCamera(this);
4343

@@ -49,18 +49,19 @@ MainWindow::MainWindow(QWidget *parent)
4949
displayModel = new GLWidget(ui->displayWidget);
5050
ui->displayLayout->addWidget(displayModel);
5151

52-
/*****生成设置窗口并输出默认设置*****/
52+
///------生成设置窗口并输出默认设置----------/
5353
setDialog = new Set(this);//Initialize the set dialog
5454
getSetInfo();
5555

56+
5657
/*****获取屏幕尺寸信息*****/
5758
getScreenGeometry();//Get mian screen and projector screen geometry
5859
QDesktopWidget* desktopWidget = QApplication::desktop();
5960
QRect projRect = desktopWidget->screenGeometry(1);//1 represent projector
6061
int xOffSet = (projRect.width() - scanWidth)/2 + screenWidth;
6162
int yOffSet = (projRect.height() - scanHeight)/2;
6263

63-
/*****初始化投影窗口*****/
64+
///----------------------------------------------初始化投影窗口-----------------------------------------------/
6465
pj = new Projector(NULL, scanWidth, scanHeight, projectorWidth, projectorHeight, xOffSet, yOffSet);//Initialize the projector
6566
pj->move(screenWidth,0);//make the window displayed by the projector
6667
pj->showFullScreen();
@@ -335,7 +336,7 @@ void MainWindow::calibration()
335336
ui->progressBar->setValue(100);
336337
}
337338

338-
///-----------------------扫描---------------------------///
339+
///------------------------------扫描---------------------------///
339340
void MainWindow::scan()
340341
{
341342
ui->progressBar->reset();
@@ -368,7 +369,7 @@ void MainWindow::scan()
368369

369370
void MainWindow::pointmatch()
370371
{
371-
dm->blocksize = ui->binarySlider->value();
372+
dm->blocksize = 41;
372373
findPoint();
373374
}
374375

@@ -382,9 +383,7 @@ void MainWindow::refindmatch()
382383
void MainWindow::findPoint()
383384
{
384385
if (dm->dotForMark.size() != 0)
385-
{
386386
dm->dotForMark.clear();
387-
}
388387
cv::Mat mat_1 = cv::Mat(cameraHeight, cameraWidth, CV_8UC1, DHC->m_pRawBuffer_1);//直接从内存缓冲区获得图像数据是可行的
389388
cv::Mat mat_2 = cv::Mat(cameraHeight, cameraWidth, CV_8UC1, DHC->m_pRawBuffer_2);
390389
//imshow("d",mat_1);
@@ -402,6 +401,9 @@ void MainWindow::findPoint()
402401
ui->manualWindow->setEnabled(true);
403402
connect(ui->manualWindow,SIGNAL(clicked()),this,SLOT(showhidemanual()));
404403
}
404+
else {
405+
finishmanualmatch();
406+
}
405407
}
406408
else{
407409
paintPoints();
@@ -487,21 +489,15 @@ void MainWindow::startscan()
487489

488490
DHC->closeCamera();
489491
timer->stop();
490-
pj->displaySwitch(false);
491492
pj->opencvWindow();
493+
492494
if (codePatternUsed == GRAY_ONLY){
493-
grayCode = new GrayCodes(scanWidth,scanHeight,false);
494-
grayCode->generateGrays();
495495
pj->showMatImg(grayCode->grayCodes[0]);
496496
}
497497
else if (codePatternUsed == GRAY_EPI){
498-
grayCode = new GrayCodes(scanWidth,scanHeight,true);
499-
grayCode->generateGrays();
500498
pj->showMatImg(grayCode->grayCodes[0]);
501499
}
502500
else{
503-
mf = new MultiFrequency(this, scanWidth, scanHeight);
504-
mf->generateMutiFreq();
505501
pj->showMatImg(mf->MultiFreqImages[0]);
506502
}
507503
progressPop(6);
@@ -682,12 +678,18 @@ void MainWindow::getSetInfo()
682678
switch (setDialog->usedPattern){
683679
case 0:
684680
codePatternUsed = GRAY_ONLY;
681+
grayCode = new GrayCodes(scanWidth,scanHeight,false);
682+
grayCode->generateGrays();
685683
break;
686684
case 1:
687685
codePatternUsed = GRAY_EPI;
686+
grayCode = new GrayCodes(scanWidth,scanHeight,true);
687+
grayCode->generateGrays();
688688
break;
689689
case 2:
690690
codePatternUsed = MULTIFREQ_EPI;
691+
mf = new MultiFrequency(this, scanWidth, scanHeight);
692+
mf->generateMutiFreq();
691693
}
692694
}
693695

@@ -726,7 +728,6 @@ void MainWindow::createConnections()
726728
connect(ui->actionChinese, SIGNAL(triggered()), this, SLOT(switchlanguage()));
727729
connect(ui->actionEnglish, SIGNAL(triggered()), this, SLOT(switchlanguage()));
728730
connect(ui->pSizeValue, SIGNAL(valueChanged(int)), this, SLOT(changePointSize(int)));
729-
connect(ui->loadTest, SIGNAL(clicked()), this, SLOT(loadTestModel()));
730731

731732
connect(ui->actionExit, SIGNAL(triggered()), pj, SLOT(close()));//解决投影窗口不能关掉的问题
732733
connect(ui->actionExit, SIGNAL(triggered()), fa, SLOT(close()));

0 commit comments

Comments
 (0)