代码
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/video.hpp>
using namespace cv;
using namespace std;
//全局变量声明
Mat g_srcImage, g_dstImage;//原始图和效果图
int g_nElementShape = MORPH_RECT; //元素结构的形状
//变量接收的TrackBar位置参数
int g_nMaxiterationNum = 10;
int g_nOpenCloseNum = 0;
int g_nErodeDilateNum = 0;
int g_nTopBlackHatNum = 0;
//全局函数声明 回调
static void on_OpenClose(int, void*);
static void on_ErodeDilate(int, void*);
static void on_TopBlackHat(int, void*);
int main(int argc, char** argv)
{
//载入原图
g_srcImage = imread("700levi.jpg");
namedWindow("原始图");
imshow("原始图", g_srcImage);
//创建三个窗口
namedWindow("开闭运算", 1);
namedWindow("腐蚀膨胀");
namedWindow("顶帽黑帽");
//参数赋值
g_nOpenCloseNum = 9;
g_nErodeDilateNum = 9;
g_nTopBlackHatNum = 2;
//分别给三个窗口创建滚动条
createTrackbar("迭代值", "开闭运算", &g_nOpenCloseNum, g_nMaxiterationNum * 2 + 1, on_OpenClose);
createTrackbar("迭代值", "腐蚀膨胀", &g_nErodeDilateNum, g_nMaxiterationNum * 2 + 1, on_ErodeDilate);
createTrackbar("迭代值", "顶帽黑帽", &g_nTopBlackHatNum, g_nMaxiterationNum * 2 + 1, on_TopBlackHat);
while (1)
{
int c;
//执行回调函数
on_OpenClose(g_nOpenCloseNum, 0);
on_ErodeDilate(g_nOpenCloseNum, 0);
on_TopBlackHat(g_nOpenCloseNum, 0);
//获取按键
c = waitKey(0);
if (char(c) == 'q' || char(c) == 27)
{
break;
}
if (char(c) == 49)// 1 切换内核的形状椭圆形
{
g_nElementShape = MORPH_ELLIPSE;
}
else if(char(c) == 50) { //2 切换为矩形
g_nElementShape = MORPH_RECT;
}else if (char(c) == 51){// 3 切换为交叉形
g_nElementShape = MORPH_CROSS;
}else if (char(c) == ' ') {
//循环
g_nElementShape = (g_nElementShape + 1) % 3;
}
}
return 0;
}
void on_OpenClose(int, void*) {
//偏移量定义
int offset = g_nOpenCloseNum - g_nMaxiterationNum; //偏移量
int Absolute_offset = offset > 0 ? offset : -offset;
//自定义核
Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
//进行操作
if (offset < 0)
{
morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);
}
else
{
morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);
}
imshow("开闭运算", g_dstImage);
}
void on_ErodeDilate(int, void*) {
//偏移量定义
int offset = g_nErodeDilateNum - g_nMaxiterationNum;
int Absolute_offset = offset > 0 ? offset : -offset;//偏移量绝对值
//自定义核
Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
//进行操作
if (offset < 0)
{
erode(g_srcImage, g_dstImage, element);
}
else
{
dilate(g_srcImage, g_dstImage, element);
}
imshow("腐蚀膨胀", g_dstImage);
}
void on_TopBlackHat(int, void*) {
int offset = g_nTopBlackHatNum - g_nMaxiterationNum;
int Absolute_offset = offset > 0 ? offset : -offset;
Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
//进行操作
if (offset < 0)
{
morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);
}
else
{
morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);
}
imshow("顶帽黑帽", g_dstImage);
}
效果
补充
这个例程可玩性还是挺高的, 可以通过按键123来改变内核的形状, 也可以通过滚动条来控制内核的大小.后面需要继续琢磨总结.