ToolsMenu::ToolsMenu(ImageViewer* iv, QWidget* parent) : QWidget(parent), ui(new Ui::ToolsMenu) { ui->setupUi(this); setLayout(ui->verticalLayoutWidget->layout()); m_viewer = (ImageViewer*) iv; m_tools = new Tools(m_viewer, this); // locking tools menu when performing transformation connect(m_viewer, SIGNAL(lockTools()), this, SLOT(disableAllTools())); connect(m_viewer, SIGNAL(unlockTools()), this, SLOT(enableAllTools())); /* ------------------------------------------------------- * ROTATION * ------------------------------------------------------- */ connect(ui->rotate90Button, SIGNAL(clicked()), m_tools, SLOT(rotate90())); connect(ui->rotate180Button, SIGNAL(clicked()), m_tools, SLOT(rotate180())); connect(ui->rotate270Button, SIGNAL(clicked()), m_tools, SLOT(rotate270())); /* ------------------------------------------------------- * HISTOGRAM * ------------------------------------------------------- */ QMenu* hMenu = new QMenu(ui->histogramButton); hMenu->addAction( QIcon(":/icons/icons/chart_curve_error.png"), QString("Equalize histograms"), m_tools, SLOT(histogramEqualize()) ); hMenu->addAction( QIcon(":/icons/icons/chart_curve_go.png"), QString("Stretch histograms"), m_tools, SLOT(histogramStretch()) ); ui->histogramButton->setMenu(hMenu); /* ------------------------------------------------------- * FILTERS (convolution, blur) * ------------------------------------------------------- */ QMenu* bMenu = new QMenu(ui->blurButton); bMenu->addAction( QIcon(":/icons/icons/draw_convolve.png"), QString("Gaussian blur"), m_tools, SLOT(blurGauss()) ); bMenu->addAction( QIcon(":/icons/icons/draw_convolve.png"), QString("Uniform blur"), m_tools, SLOT(blurUniform()) ); bMenu->addAction( QIcon(":/icons/icons/flag_airfield_vehicle_safety.png"), QString("Custom linear filter"), m_tools, SLOT(blurLinear()) ); ui->blurButton->setMenu(bMenu); /* ------------------------------------------------------- * BINARIZATION * ------------------------------------------------------- */ QMenu* binMenu = new QMenu(ui->binarizationButton); binMenu->addAction( QIcon(":/icons/icons/universal_binary.png"), QString("Manual"), m_tools, SLOT(binManual()) ); binMenu->addAction( QIcon(":/icons/icons/universal_binary.png"), QString("Gradient"), m_tools, SLOT(binGradient()) ); binMenu->addAction( QIcon(":/icons/icons/universal_binary.png"), QString("Iterative bimodal"), m_tools, SLOT(binIterBimodal()) ); binMenu->addAction( QIcon(":/icons/icons/universal_binary.png"), QString("Niblack"), m_tools, SLOT(binNiblack()) ); binMenu->addAction( QIcon(":/icons/icons/universal_binary.png"), QString("Otsu"), m_tools, SLOT(binOtsu()) ); ui->binarizationButton->setMenu(binMenu); /* ------------------------------------------------------- * NOISE REDUCTION * ------------------------------------------------------- */ QMenu* nMenu = new QMenu(ui->noiseButton); nMenu->addAction( QIcon(":/icons/icons/checkerboard.png"), QString("Median"), m_tools, SLOT(noiseMedian()) ); nMenu->addAction( QIcon(":/icons/icons/checkerboard.png"), QString("Bilateral"), m_tools, SLOT(noiseBilateral()) ); ui->noiseButton->setMenu(nMenu); /* ------------------------------------------------------- * MORPHOLOGICAL * ------------------------------------------------------- */ QMenu* morphMenu = new QMenu(ui->morphButton); morphMenu->addAction( QIcon(":/icons/icons/arrow_out.png"), QString("Dilate"), m_tools, SLOT(morphDilate()) ); morphMenu->addAction( QIcon(":/icons/icons/arrow_in.png"), QString("Erode"), m_tools, SLOT(morphErode()) ); morphMenu->addAction( QIcon(":/icons/icons/arrow_divide.png"), QString("Open"), m_tools, SLOT(morphOpen()) ); morphMenu->addAction( QIcon(":/icons/icons/arrow_join.png"), QString("Close"), m_tools, SLOT(morphClose()) ); ui->morphButton->setMenu(morphMenu); /* ------------------------------------------------------- * EDGE DETECTION * ------------------------------------------------------- */ QMenu* eMenu = new QMenu(ui->edgeButton); eMenu->addAction( QIcon(":/icons/icons/key_s.png"), QString("Sobel"), m_tools, SLOT(edgeSobel()) ); eMenu->addAction( QIcon(":/icons/icons/key_p.png"), QString("Prewitt"), m_tools, SLOT(edgePrewitt()) ); eMenu->addAction( QIcon(":/icons/icons/key_r.png"), QString("Roberts"), m_tools, SLOT(edgeRoberts()) ); eMenu->addAction( QIcon(":/icons/icons/edge_detection.png"), QString("Laplacian"), m_tools, SLOT(edgeLaplacian()) ); eMenu->addAction( QIcon(":/icons/icons/edge_detection.png"), QString("Zero-crossing (LoG)"), m_tools, SLOT(edgeZero()) ); eMenu->addAction( QIcon(":/icons/icons/edge_detection.png"), QString("Canny"), m_tools, SLOT(edgeCanny()) ); ui->edgeButton->setMenu(eMenu); /* ------------------------------------------------------- * TEXTURES * ------------------------------------------------------- */ QMenu* texMenu = new QMenu(ui->textureButton); texMenu->addAction( QIcon(":/icons/icons/flag_airfield_vehicle_safety.png"), QString("Height map"), m_tools, SLOT(mapHeight()) ); texMenu->addAction( QIcon(":/icons/icons/flag_airfield_vehicle_safety.png"), QString("Normal map"), m_tools, SLOT(mapNormal()) ); texMenu->addAction( QIcon(":/icons/icons/flag_airfield_vehicle_safety.png"), QString("Horizon map"), m_tools, SLOT(mapHorizon()) ); ui->textureButton->setMenu(texMenu); /* ------------------------------------------------------- * TRANSFORMATIONS * ------------------------------------------------------- */ QMenu* transMenu = new QMenu(ui->transformationsButton); transMenu->addAction( QIcon(":/icons/icons/videodisplay.png"), QString("Hough"), m_tools, SLOT(houghTransform()) ); transMenu->addAction( QIcon(":/icons/icons/videodisplay.png"), QString("Hough - lines"), m_tools, SLOT(houghLines()) ); transMenu->addAction( QIcon(":/icons/icons/videodisplay.png"), QString("Hough - rectangles"), m_tools, SLOT(houghRectangles()) ); transMenu->addAction( QIcon(":/icons/icons/videodisplay.png"), QString("Segmentation"), m_tools, SLOT(segmentation()) ); ui->transformationsButton->setMenu(transMenu); /* ------------------------------------------------------- * CORNER DETECTION * ------------------------------------------------------- */ QMenu* cornerMenu = new QMenu(ui->cornerButton); cornerMenu->addAction( QIcon(":/icons/icons/things_digital.png"), QString("Harris"), m_tools, SLOT(cornerHarris()) ); ui->cornerButton->setMenu(cornerMenu); }
std::vector<PointId> PMFFilter::processGround(PointViewPtr view) { point_count_t np(view->size()); // Compute the series of window sizes and height thresholds std::vector<float> height_thresholds; std::vector<float> window_sizes; int iteration = 0; float window_size = 0.0f; float height_threshold = 0.0f; while (window_size < m_maxWindowSize) { // Determine the initial window size. if (1) // exponential window_size = m_cellSize * (2.0f * std::pow(2, iteration) + 1.0f); else window_size = m_cellSize * (2.0f * (iteration+1) * 2 + 1.0f); // Calculate the height threshold to be used in the next iteration. if (iteration == 0) height_threshold = m_initialDistance; else height_threshold = m_slope * (window_size - window_sizes[iteration-1]) * m_cellSize + m_initialDistance; // Enforce max distance on height threshold if (height_threshold > m_maxDistance) height_threshold = m_maxDistance; window_sizes.push_back(window_size); height_thresholds.push_back(height_threshold); iteration++; } std::vector<PointId> groundIdx; for (PointId i = 0; i < np; ++i) groundIdx.push_back(i); // Progressively filter ground returns using morphological open for (size_t j = 0; j < window_sizes.size(); ++j) { // Limit filtering to those points currently considered ground returns PointViewPtr ground = view->makeNew(); for (PointId i = 0; i < groundIdx.size(); ++i) ground->appendPoint(*view, groundIdx[i]); printf(" Iteration %ld (height threshold = %f, window size = %f)...", j, height_thresholds[j], window_sizes[j]); // Create new cloud to hold the filtered results. Apply the morphological // opening operation at the current window size. auto maxZ = morphOpen(ground, window_sizes[j]*0.5); // Find indices of the points whose difference between the source and // filtered point clouds is less than the current height threshold. std::vector<PointId> pt_indices; for (PointId i = 0; i < ground->size(); ++i) { double z0 = ground->getFieldAs<double>(Dimension::Id::Z, i); double z1 = maxZ[i]; float diff = z0 - z1; if (diff < height_thresholds[j]) pt_indices.push_back(groundIdx[i]); } groundIdx.swap(pt_indices); } return groundIdx; }