opencv图像求差的绝对值cvAbsDiff和形态学开运算cvMorphologyEx

AbsDiff与cvMorphologyEx

我们先来学习图像求差的绝对值这个函数:AbsDiff,它的作用是:OpenCV 中计算两个数组差的绝对值的函数。


函数原型:
void cvAbsDiff( const CvArr* src1, const CvArr* src2, CvArr* dst );

src1:第一个原数组
src2:第二个原数组
dst:输出数组

原理是:dst(I)c = abs(src1(I)c - src2(I)c).
所有数组必须有相同的数据类型相同的大小(或ROI大小)

拓展一下:

AbsDiffS:计算数组元素与数量之间差的绝对值,注意与上面不同的是数量value。


void cvAbsDiffS( const CvArr* src, CvArr* dst, CvScalar value );

#define cvAbs(src, dst) cvAbsDiffS(src, dst, cvScalarAll(0))

src:原数组.
dst:输出数组
value:数量.

原理是:dst(I)c = abs(src(I)c - valuec).

所有数组必须有相同的数据类型相同的大小(或ROI大小)


然后,我们学习形态学转换开运算cvMorphologyEx这个函数。

void cvMorphologyEx(const CvArr* src, CvArr* dst, CvArr* tmp, IplConvKernel* element, int operation, int iterations = 1);

参数说明:

src:输入图像
dst:输出图像
tmp:临时图像,某些操作会用到。需要使用tmp时,它应与原图像有同样的大小
element:结构元素
operation:形态操作的类型,有以下几种可用的类型:
-CV_MOP_OPEN开运算不需要临时图像
-CV_MOP_CLOSE闭运算不需要临时图像
-CV_MOP_GRADIENT形态梯度需要临时图像
-CV_MOP_TOPHAT“礼帽”src = dst情况下需要
-CV_MOP_BLACKHAT”黑帽“src = dst情况下需要


开运算:是先腐蚀然后再膨胀:dst = open(src, element) = dilate(erode(src, element), element)。开运算通常可以用来统计二值图像中的区域属,如已将显微镜载玻片上观察到的细胞图像作了阈值化处理,可以使用开运算将相邻的细胞分离开来,然后再计算图像中的区域细胞数目。


闭运算:是先膨胀然后再腐蚀:dst = close(src, element) = erode(dilate(src, element), element)。在大多数好的连通区域分析算法中,都会用到闭运算来除去噪声引起的区域。对于连通区域分析,通常采用腐蚀或闭运算来消除纯粹由噪声引起的部分,然后用开运算来连接邻近的区域。


形态学梯度:膨胀图像减去腐蚀图像:dst = dilate(src, element) - erode(src, element)。形态学梯度操作能描述图像亮度变化的剧烈程度。当想突出亮度区域的外围时,通常可使用形态学梯度,这样可以把高亮的看成一个整体。因为从原区域的膨胀中减去了原区域的收缩,所以留下了完整的外围边缘。


礼帽操作:dst = src - open(src, element)
黑帽操作:dst = close(src, element) - src
这两个操作分别用于分离比邻近的点亮或暗的一些斑块。


题目描述:

拍一张某场景的图片,然后相机不动,在此场景中心位置放一个杯子,再拍一张图片,将其载入电脑并转换为8位灰度图像

a、求其差的绝对值并显示结果,他应该是一个带有噪声的杯子的掩码,
b、对结果图像进行二值化操作,剔除噪声的同时并保留鼠标,超过阈值的像素应设为255
c、在图像上进行CV_MOP_OPEN操作,进一步清除噪声

代码:

#include <cv.h>
#include <highgui.h>
#include <iostream>
using namespace cv;
using namespace std;
//函数声明-->--->-->--->-->--->-->--->//
//<--<--<--<--<--<--<--<--<--函数声明//
int main()
{
    const char * fileName1 = "D:\\VC98\\C++项目\\opencv\\cvMorphologyEx_1\\cvMorphologyEx_1\\cup.jpg";
    const char * fileName2 = "D:\\VC98\\C++项目\\opencv\\cvMorphologyEx_1\\cvMorphologyEx_1\\cup1.jpg";
    IplImage * src1 = cvLoadImage(fileName1, CV_LOAD_IMAGE_GRAYSCALE);
    IplImage * src2 = cvLoadImage(fileName2, CV_LOAD_IMAGE_GRAYSCALE);
    assert(src1);
    assert(src2);
    //IplImage * img = cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 1);
    //assert(img); 
    //cvZero(img);
    //cvSetReal2D(img, 49, 49, 255);    
     
    cvNamedWindow("原始图像1", 0);    
    cvNamedWindow("原始图像2", 0);
    cvNamedWindow("题目_a", 0);
    cvNamedWindow("题目_b", 0);
    cvNamedWindow("题目_c", 0);
    //cvNamedWindow("题目_d", 0);
    /*char * imageName = "E:\\Testing\\Image\\ExerciseWindow.jpg";
    cvSaveImage(imageName, img);*/
    cvShowImage("原始图像1", src1);
    cvShowImage("原始图像2", src2);   
    //---------------------------a:开始--------------------------------//
    IplImage * diff12 = cvCloneImage(src1);
    cvZero(diff12);
    cvAbsDiff(src1, src2, diff12);
    cvShowImage("题目_a", diff12);
cvSaveImage("result.jpg",diff12);
    /*char * saveName = "E:\\Testing\\Image\\SavePath\\diff12.jpg";
    cvSaveImage(saveName, diff12);*/
    //---------------------------a:结束--------------------------------//    
    //---------------------------b:开始--------------------------------//
    IplImage * cleandiff = cvCloneImage(diff12);
    cvZero(cleandiff);
    //针对有很强照明或反射梯度的图像,需要根据梯度进行阈值化时,自适应技术非常有用,看图5-24的处理结果对比很明显
    cvThreshold(diff12, cleandiff, 64, 255, CV_THRESH_BINARY);
    cvShowImage("题目_b", cleandiff);
cvSaveImage("result1.jpg",cleandiff);
    /*saveName = "E:\\Testing\\Image\\SavePath\\image_open.jpg";
    cvSaveImage(saveName, cleandiff);*/
    //---------------------------b:结束--------------------------------//    
    //---------------------------c:开始--------------------------------//
    IplImage * dirtydiff = cvCloneImage(cleandiff);
    cvZero(dirtydiff);
    IplConvKernel * kernel = cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_RECT);
    cvMorphologyEx(cleandiff, dirtydiff, NULL, kernel, CV_MOP_OPEN,2);
    cvShowImage("题目_c", dirtydiff);
cvSaveImage("result2.jpg",dirtydiff);
    /*saveName = "E:\\Testing\\Image\\SavePath\\image_close.jpg";
    cvSaveImage(saveName, dirtydiff);*/
    //---------------------------c:结束--------------------------------//     
    cvWaitKey(0);

    cvReleaseImage(&src1);
    cvReleaseImage(&src2);
    cvReleaseImage(&diff12);
    cvReleaseImage(&cleandiff);
    cvReleaseImage(&dirtydiff);

    cvDestroyWindow("原始图像1");     
    cvDestroyWindow("原始图像2");
    cvDestroyWindow("题目_a");
    cvDestroyWindow("题目_b");
    cvDestroyWindow("题目_c");
    //cvDestroyWindow("题目_d");
    return 0;
}

结果:

输入的两张图片:

opencv图像求差的绝对值cvAbsDiff和形态学开运算cvMorphologyEx_第1张图片

opencv图像求差的绝对值cvAbsDiff和形态学开运算cvMorphologyEx_第2张图片

题目_a:

opencv图像求差的绝对值cvAbsDiff和形态学开运算cvMorphologyEx_第3张图片

题目_b:

opencv图像求差的绝对值cvAbsDiff和形态学开运算cvMorphologyEx_第4张图片

题目_c:

opencv图像求差的绝对值cvAbsDiff和形态学开运算cvMorphologyEx_第5张图片



你可能感兴趣的:(opencv,图像处理)