我即将完成一个带有多个控件的用户界面,但是我有一个问题,我已经苦苦挣扎了一段时间。在QGraphicsView(左)上有一个图像(例如,黑白),例如图像A。在另一个QGraphicsView(右)上,我具有相同的图像,例如图像B,我将其从RGB转换为黑白。 一旦我单击左视图,便捕获了一个点,然后在右视图中,我试图找到相同的匹配项。 下图中是现在正在发生的事情:
该算法可以工作并找到匹配项,但是速度很慢。我试图限制搜索区域,以便在图像B上从从A到B的间隔开始查找,而不是在整行中搜索。 低于预期的结果:
下面,我附上进行搜索和匹配的代码的主要部分:
windowingDialog::windowingDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::windowingDialog)
{
ui->setupUi(this);
viewerScene = new WinGraphicsScene();
ui->graphicsA->setScene(viewerScene);
viewerSceneRight = new WinGraphicsScene();
ui->graphicsB->setScene(viewerSceneRight);
searchArea = new QGraphicsRectItem(0, 0, 0, 0);
searchArea->setPen(QPen(QBrush(Qt::red), 20));
viewerScene->addItem(searchArea);
ui->graphicsA->show();
searchingArea = new QGraphicsRectItem(0, 0, 0, 0);
searchingArea->setPen(QPen(QBrush(Qt::red), 20));
viewerSceneRight->addItem(searchingArea);
ui->graphicsB->show();
}
bool windowingDialog::matchImages(QPointF point) {
StereoCal match;
match.readFile("/path/to/file.yml");
StereoImage imagePair = listPtr->getImage(ui->listWidgetGraphA->currentRow());
imagePair.getA().toGrey();
imagePair.getA().to8Bit();
imagePair.getB().toGrey();
imagePair.getB().to8Bit();
match.rectifyImages(imagePair);
match.setRegionSize(ui->regionSizeSpinBox->value());
match.clickPoint.x = (int)point.x();
match.clickPoint.y = (int)point.y();
cv::Point updatedPoint=match.checkPoint(match.clickPoint.x, match.clickPoint.y);
// Area to search for on the second image
searchArea->setRect(updatedPoint.x-ui->regionSizeSpinBox->value()/2, updatedPoint.y-ui->regionSizeSpinBox->value()/2, ui->regionSizeSpinBox->value(), ui->regionSizeSpinBox->value());
searchArea->setZValue(1);
ui->graphicsA->show();
// Area we're searching on the second image
searchingArea->setRect(0, updatedPoint.y-ui->regionSizeSpinBox->value()/2, ui->regionSizeSpinBox->value(), ui->regionSizeSpinBox->value());
searchingArea->setZValue(1);
ui->graphicsB->show();
QApplication::processEvents();
BestMatch best = match.findMatchedRegion(ui->matchProgressBarLeft, searchingArea, point.x(),point.y());
ui->bestMatchPositionLineEdit->setText(QString::number(best.best));
searchingArea->setPos(QPointF(best.best, searchingArea->pos().y()));
}
stereocal.h
void setRegionSize(int sz){regionSize=sz; km = (regionSize-1)/2;}
BestMatch findMatchedRegion(QProgressBar* progress, QGraphicsRectItem* target, int u, int v);
stereocal.cpp
//Find match for rectified image pairs
// Where I click automatically the region is set around the click.
BestMatch StereoCal::findMatchedRegion(QProgressBar* progress, QGraphicsRectItem* target, int u, int v){
cv::Point updatedPoint=checkPoint(u, v);
int xa = updatedPoint.y;
int ya = updatedPoint.x;
std::vector<double> errorVect;
if(progress != NULL)
progress->setRange(0, currentImages.getB().getBitmap().size().width-km);
for(size_t i=km; i<currentImages.getB().getBitmap().size().width-km; i++){
double error;
error=getError(xa, ya, i, ya);
errorVect.push_back(error);
if(progress != NULL)
progress->setValue(i);
target->setPos(QPointF(i, target->pos().y()));
QApplication::processEvents();
}
if(progress != NULL)
progress->setValue(progress->value()+1);
// we have to add km to take into account the serach started at k.
// adjusts position in your vector back to pixel coordinate
int best=getMin1D(errorVect, xa) +km;
// the center of clicked point will be over the row
int disparity = xa-best;
cv::Point2f ptA, ptB;
ptA.x=xa; ptA.y=ya;
ptB.x=best; ptB.y=ya;
std::vector<cv::Point2f> vA, nvA, vB, nvB;
vA.push_back(ptA);vB.push_back(ptB);
cropMatches(xa, ya, best, ya);
cv::Vec3d adjpoint = triangulatePoints(vA,vB);
BestMatch returnMatch;
returnMatch.best = best;
returnMatch.errvec = errorVect[best];
returnMatch.disparity = disparity;
returnMatch.fullError = errorVect;
returnMatch.calculatedPoint = adjpoint;
return returnMatch;
}
//Calculate SSD for pixel-centered regions
double StereoCal::getError(int xa, int ya, int xb /* xb is the only changing for now*/, int yb){
double error=0.0;
Image aT,bT;
cv::Mat a,b;
aT=currentImages.getA();
if(aT.getBitmap().channels() > 2) {
aT.toGrey();
}
aT.getBitmap().convertTo(a, CV_32F);
bT=currentImages.getB();
if(bT.getBitmap().channels() > 2) {
bT.toGrey();
}
bT.getBitmap().convertTo(b, CV_32F);
for (int kx = -km; kx <= km; kx++){
for(int ky = -km; ky <= km; ky++){
error += std::pow((a.at<float>(ya+kx,xa+ky)-b.at<float>(yb+kx,xb+ky)),2);
}
}
return error;
}
// Min error along epipolar line
int StereoCal::getMin1D(std::vector<double> vec, int x){
int pos=0;
double min = vec[0];
for(int i=1; i< vec.size(); i++){
if(vec[i]<min){
pos=i;
min =vec[i];
}
}
return pos;
}
感谢您对此问题的理解或指出正确的方向