目录
一、前言
本文旨在快速过一下图像基本操作,不做过多原理解释。代码都有,具体细节可自行琢磨,举一反三。
二、代码片段
1、膨胀
cv::Mat bin_dilate;
cv::dilate(bin, bin_dilate, element);
cv::imshow("bin_dilate", bin_dilate);
cv::waitKey(0);
2、腐蚀
cv::Mat bin_erode;
cv::erode(bin, bin_erode, element);
cv::imshow("bin_erode", bin_erode);
cv::waitKey(0);
3、开运算
cv::Mat bin_open;
cv::morphologyEx(bin, bin_open, cv::MORPH_OPEN, element);
cv::imshow("bin_open", bin_open);
cv::waitKey(0);
4、闭运算
cv::Mat bin_close;
cv::morphologyEx(bin, bin_close, cv::MORPH_CLOSE, element);
cv::imshow("bin_close", bin_close);
cv::waitKey(0);
5、顶帽运算
cv::Mat bin_top;
cv::morphologyEx(bin, bin_top, cv::MORPH_TOPHAT, element);
cv::imshow("bin_top", bin_top);
cv::waitKey(0);
6、黑帽运算
cv::Mat bin_black;
cv::morphologyEx(bin, bin_black, cv::MORPH_BLACKHAT, element);
cv::imshow("bin_black", bin_black);
cv::waitKey(0);
7、梯度运算
cv::Mat bin_grad;
cv::morphologyEx(bin, bin_grad, cv::MORPH_GRADIENT, element);
cv::imshow("bin_grad", bin_grad);
cv::waitKey(0);
8、连通域分割
cv::Mat labels;
int num = cv::connectedComponents(bin, labels, 4, CV_16U);
9、连通域可视化
cv::Mat mat_show;
cv::normalize(labels, mat_show, 255, 0, cv::NORM_MINMAX);
cv::convertScaleAbs(mat_show, mat_show);
cv::applyColorMap(mat_show, mat_show, cv::COLORMAP_JET);
cv::imshow("mat_show", mat_show);
cv::waitKey(0);
10、最大连通域提取
std::vector<int> num_of_labels;
for (int i = 0; i < num; i++)// 初始化 所有label的初值均设置为0
num_of_labels.push_back(0);
int rows = labels.rows;
int cols = labels.cols;
for (int row = 0; row < rows; row++) { //计算连通域的面积
for (int col = 0; col < cols; col++){
num_of_labels.at(labels.at<unsigned short>(row, col)) += 1;
}
}
num_of_labels.at(0) = 0; //将背景的labels个数设置为0
int max_label = -1;
int max_area = -1;
for (int i = 0; i < num_of_labels.size(); i++){ // 找出最大面积的label
if (num_of_labels[i] > max_area){
max_label = i;
max_area = num_of_labels[i];
}
}
cv::Mat max_connected_domain = cv::Mat::zeros(bin.size(),CV_8UC1);
for (int r = 0; r < bin.rows; r++){
for (int c = 0; c < bin.cols; c++){
if (labels.at<unsigned short>(r, c) == max_label){
max_connected_domain.at<uchar>(r, c) = 255;
}
}
}
cv::imshow("max_connected_domain", max_connected_domain);
cv::waitKey(0);
三、完整代码
#include <opencv2/opencv.hpp>
#include <opencv2/core/utils/logger.hpp>
int main()
{
cv::utils::logging::setLogLevel(cv::utils::logging::LOG_LEVEL_ERROR);
cv::Mat src = cv::imread("people.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat bin;
cv::threshold(src, bin, 125, 255, cv::THRESH_BINARY||cv::THRESH_OTSU);
cv::imshow("bin", bin);
cv::waitKey(0);
//获取自定义形态学核
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
// 1、膨胀
cv::Mat bin_dilate;
cv::dilate(bin, bin_dilate, element);
cv::imshow("bin_dilate", bin_dilate);
cv::waitKey(0);
// 2、腐蚀
cv::Mat bin_erode;
cv::erode(bin, bin_erode, element);
cv::imshow("bin_erode", bin_erode);
cv::waitKey(0);
// 3、开运算
cv::Mat bin_open;
cv::morphologyEx(bin, bin_open, cv::MORPH_OPEN, element);
cv::imshow("bin_open", bin_open);
cv::waitKey(0);
// 4、闭运算
cv::Mat bin_close;
cv::morphologyEx(bin, bin_close, cv::MORPH_CLOSE, element);
cv::imshow("bin_close", bin_close);
cv::waitKey(0);
// 5、顶帽运算
cv::Mat bin_top;
cv::morphologyEx(bin, bin_top, cv::MORPH_TOPHAT, element);
cv::imshow("bin_top", bin_top);
cv::waitKey(0);
// 6、黑帽运算
cv::Mat bin_black;
cv::morphologyEx(bin, bin_black, cv::MORPH_BLACKHAT, element);
cv::imshow("bin_black", bin_black);
cv::waitKey(0);
// 7、梯度运算
cv::Mat bin_grad;
cv::morphologyEx(bin, bin_grad, cv::MORPH_GRADIENT, element);
cv::imshow("bin_grad", bin_grad);
cv::waitKey(0);
// 8、连通域分割
cv::Mat labels;
int num = cv::connectedComponents(bin, labels, 4, CV_16U);
// 9、将分割后的连通域可视化(同样适用于深度图等非8位图的可视化)
cv::Mat mat_show;
cv::normalize(labels, mat_show, 255, 0, cv::NORM_MINMAX);
cv::convertScaleAbs(mat_show, mat_show);
cv::applyColorMap(mat_show, mat_show, cv::COLORMAP_JET);
cv::imshow("mat_show", mat_show);
cv::waitKey(0);
// 10、最大连通域提取
std::vector<int> num_of_labels;
for (int i = 0; i < num; i++)// 初始化 所有label的初值均设置为0
num_of_labels.push_back(0);
int rows = labels.rows;
int cols = labels.cols;
for (int row = 0; row < rows; row++) { //计算连通域的面积
for (int col = 0; col < cols; col++){
num_of_labels.at(labels.at<unsigned short>(row, col)) += 1;
}
}
num_of_labels.at(0) = 0; //将背景的labels个数设置为0
int max_label = -1;
int max_area = -1;
for (int i = 0; i < num_of_labels.size(); i++){ // 找出最大面积的label
if (num_of_labels[i] > max_area){
max_label = i;
max_area = num_of_labels[i];
}
}
cv::Mat max_connected_domain = cv::Mat::zeros(bin.size(),CV_8UC1);
for (int r = 0; r < bin.rows; r++){
for (int c = 0; c < bin.cols; c++){
if (labels.at<unsigned short>(r, c) == max_label){
max_connected_domain.at<uchar>(r, c) = 255;
}
}
}
cv::imshow("max_connected_domain", max_connected_domain);
cv::waitKey(0);
}
四、总结:
本文对二值图像的基本操作进行简要概述,旨在为博客后续较难内容打下基础,敬请期待。