形态学滤波可用于检测图像种指定的特征,可检测灰度图种的直线和角点。
目录
1.创建MorphoFeatures类,实现检测图像特征
/*MorphoFeatures*/
class MorphoFeatures {
private:
// threshold to produce binary image
int threshold;
// structuring elements used in corner detection
cv::Mat cross;
cv::Mat diamond;
cv::Mat square;
cv::Mat x;
void applyThreshold(cv::Mat& result) {
// Apply threshold on result
if (threshold > 0)
cv::threshold(result, result, threshold, 255, cv::THRESH_BINARY_INV);
}
public:
MorphoFeatures() : threshold(-1), cross(5, 5, CV_8U, cv::Scalar(0)),
diamond(5, 5, CV_8U, cv::Scalar(1)),
square(5, 5, CV_8U, cv::Scalar(1)),
x(5, 5, CV_8U, cv::Scalar(0)) {
// Creating the cross-shaped structuring element
for (int i = 0; i < 5; i++) {
cross.at<uchar>(2, i) = 1;
cross.at<uchar>(i, 2) = 1;
}
// Creating the diamond-shaped structuring element
diamond.at<uchar>(0, 0) = 0;
diamond.at<uchar>(0, 1) = 0;
diamond.at<uchar>(1, 0) = 0;
diamond.at<uchar>(4, 4) = 0;
diamond.at<uchar>(3, 4) = 0;
diamond.at<uchar>(4, 3) = 0;
diamond.at<uchar>(4, 0) = 0;
diamond.at<uchar>(4, 1) = 0;
diamond.at<uchar>(3, 0) = 0;
diamond.at<uchar>(0, 4) = 0;
diamond.at<uchar>(0, 3) = 0;
diamond.at<uchar>(1, 4) = 0;
// Creating the x-shaped structuring element
for (int i = 0; i < 5; i++) {
x.at<uchar>(i, i) = 1;
x.at<uchar>(4 - i, i) = 1;
}
}
void setThreshold(int t) {
threshold = t;
}
int getThreshold() const {
return threshold;
}
cv::Mat getEdges(const cv::Mat &image) {
// Get the gradient image
cv::Mat result;
cv::morphologyEx(image, result, cv::MORPH_GRADIENT, cv::Mat());
// Apply threshold to obtain a binary image
applyThreshold(result);
return result;
}
cv::Mat getCorners(const cv::Mat &image) {
cv::Mat result;
// Dilate with a cross
cv::dilate(image, result, cross);
// Erode with a diamond
cv::erode(result, result, diamond);
cv::Mat result2;
// Dilate with a X
cv::dilate(image, result2, x);
// Erode with a square
cv::erode(result2, result2, square);
// Corners are obtained by differencing
// the two closed images
cv::absdiff(result2, result, result);
// Apply threshold to obtain a binary image
applyThreshold(result);
return result;
}
void drawOnImage(const cv::Mat& binary, cv::Mat& image) {
cv::Mat_<uchar>::const_iterator it = binary.begin<uchar>();
cv::Mat_<uchar>::const_iterator itend = binary.end<uchar>();
// for each pixel
for (int i = 0; it != itend; ++it, ++i) {
if (!*it)
cv::circle(image, cv::Point(i%image.step, i / image.step), 5, cv::Scalar(255, 0, 0));
}
}
};
2.实现过程:
void OpenCVQtGui::Morpho_clicked()
{
cv::Mat Result = image.clone();
/*切记图像类型转换*/
cvtColor(Result, Result, CV_BGR2GRAY);
// Create the morphological features instance
morpho.setThreshold(35);
// Get the edges
cv::Mat edges;
edges = morpho.getEdges(Result);
// Display the edge image
cv::namedWindow("Edge Image");
cv::imshow("Edge Image", edges);
//Get the corners
morpho.setThreshold(-1);
cv::Mat corners;
corners = morpho.getCorners(Result);
cv::imshow("Corner Image", corners);
cv::morphologyEx(corners, corners, cv::MORPH_TOPHAT, cv::Mat());
cv::threshold(corners, corners, 60, 255, cv::THRESH_BINARY_INV);
//Display the corner image
cv::namedWindow("Corner Image");
cv::imshow("Corner Image", corners);
// Display the corner on the image
morpho.drawOnImage(corners, Result);
cv::namedWindow("Corners on Image");
cv::imshow("Corners on Image", Result);
cvtColor(Result, Result, CV_BGR2RGB);
QImage img1 = QImage((const unsigned char*)(Result.data), Result.cols, Result.rows, QImage::Format_RGB888);
ui.label_2->setPixmap(QPixmap::fromImage(img1));
ui.label_2->resize(QSize(img1.width(), img1.height()));
}
3.验证结果