OpenCV之图像处理(十一) 膨胀与腐蚀

图像用到了各种数学的学科,集合论,形态学,统计学,卷积,求导,求微分,傅里叶变换
图像形态学操作 – 基于形状的一系列图像处理操作的合集,主要是基于集合论基础上的形态学数学
    形态学有四个基本操作:腐蚀、膨胀、开、闭
    膨胀与腐蚀是图像处理中最常用的形态学操作手段  morphology operators

形态学操作-膨胀(感官上图像变细,变白了)
    跟卷积操作类似,假设有图像A和结构元素B,结构元素B在A上面移动,其中B定义其中心为锚点,
    计算B覆盖下A的最大像素值用来替换锚点的像素,其中B作为结构体可以是任意形状
形态学操作-腐蚀(感官上图像变粗,变黑了)
    腐蚀跟膨胀操作的过程类似,唯一不同的是以最小值替换锚点重叠下图像的像素值

VS代码

    #include "../common/common.hpp"

    static Mat src, dst1, dst2;
    static char output1[64] = "output1";
    static char output2[64] = "output2";
    static int element_size = 3;
    static int max_size = 21;
    static void CallBack_Demo(int, void *);

    void main1_11(int argc, char** argv)
    {
        src = imread(getCVImagesPath("images/bintest.png"), IMREAD_COLOR);
        imshow("src", src);

        namedWindow(output1, CV_WINDOW_AUTOSIZE);//不加此句代码 Trackbar 显示不出来
        //生成一个滑动条,参数:Trackbar名字,放到哪个窗口,Trackbar初始值,Trackbar最大值,回调函数
        createTrackbar("Elemet Size1 :", output1, &element_size, max_size, CallBack_Demo);
        CallBack_Demo(0, 0);

        waitKey(0);
    }

    void CallBack_Demo(int, void *)
    {
        int s = element_size * 2 + 1;
        //获取元素结构,参数:形状 (MORPH_RECT \MORPH_CROSS \MORPH_ELLIPSE),大小,锚点 默认是Point(-1, -1)中心点
        Mat structureElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));
        //膨胀,参数1表示迭代运行1次,Scalar添加边框颜色同时膨胀,默认没有
        dilate(src, dst1, structureElement, Point(-1, -1), 1, 0, Scalar(0, 0, 255));
        erode(src, dst2, structureElement, Point(-1, -1), 1, 0, Scalar(0, 0, 255));//腐蚀,参数与膨胀一样
        imshow(output1, dst1);
        imshow(output2, dst2);
    }

效果图

这里写图片描述

Android代码

@BindView(R.id.abs_cv1_11) AppCompatSeekBar mAppCompatSeekBar;
@BindView(R.id.iv_cv1_11_input) ImageView mInputIv;
@BindView(R.id.iv_cv1_11_output1) ImageView mOutput1Iv;
@BindView(R.id.iv_cv1_11_output2) ImageView mOutput2Iv;
private Bitmap mInputBmp;
private Bitmap mOutput1Bmp;
private Bitmap mOutput2Bmp;
private Mat mInputMat = new Mat();
private Mat mOutput1Mat = new Mat();
private Mat mOutput2Mat = new Mat();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_cv1_11);
    mUnbinder = ButterKnife.bind(this);

    //input
    mInputBmp = CV310Utils.getBitmapFromAssets(this, "opencv/bintest.png");
    mInputIv.setImageBitmap(mInputBmp);
    Utils.bitmapToMat(mInputBmp, mInputMat);
    initBitmaps(mInputBmp);

    mAppCompatSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            dilate_erode(progress);
        }
        @Override
        public void onStartTrackingTouch(SeekBar seekBar) { }
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) { }
    });
    mAppCompatSeekBar.setProgress(1);
}

/*初始化bitmap*/
private void initBitmaps(Bitmap bmp){
    mOutput1Bmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.RGB_565);
    mOutput2Bmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.RGB_565);
}

/*膨胀与腐蚀*/
private void dilate_erode(int elementSize) {
    int s = elementSize *2 + 1;
    //获取元素结构,参数:形状 (MORPH_RECT \MORPH_CROSS \MORPH_ELLIPSE),大小,锚点 默认是Point(-1, -1)中心点
    Mat structureElement = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(s, s), new Point(-1, -1));
    //膨胀,参数1表示迭代运行1次,Scalar边框颜色
    Imgproc.dilate(mInputMat, mOutput1Mat, structureElement, new Point(-1, -1), 1, 0, new Scalar(255, 0, 0, 64));
    Imgproc.erode(mInputMat, mOutput2Mat, structureElement, new Point(-1, -1), 1, 0, new Scalar(255, 0, 0, 64));//腐蚀,参数与膨胀一样
    CV310Utils.mat2bitmapAndShowInIv(mOutput1Mat, mOutput1Bmp, mOutput1Iv);
    CV310Utils.mat2bitmapAndShowInIv(mOutput2Mat, mOutput2Bmp, mOutput2Iv);
}

效果图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/huanghuangjin/article/details/80945770