计算机图形图像处理 实验一

来源:互联网 发布:陈坤 厂花 知乎 编辑:程序博客网 时间:2024/05/16 07:01

计算机图形图像实验

  • 计算机图形图像实验
    • 一 图像处理初步
      • opencv安装配置
      • 图像读取与显示
      • 图像信息
    • 二 图像基本运算
      • 加减乘除
        • 图形相加
        • 图形相减
        • 图像相乘
        • 图像相除
      • 图像灰度级变换
        • 图像求反
      • 图像变换
        • 图像平移
        • 图像缩放
        • 图像旋转
      • 直方图均衡化处理

一. 图像处理初步

1. opencv安装,配置

VS配置opencv时,要修改三个地方,如下图

这里写图片描述

这里写图片描述

2.图像读取与显示

//CvArr//CvMat 是CvArr的子类//IplImage 是CvMat的子类,这里使用IplImage读取和显示文件IplImage* img1 = cvLoadImage(imagename1);cvShowImage("title", img);cvWaitKey(0);//释放内存cvReleaseImage(&img1);//销毁窗口cvDestroyWindow("title");

3.图像信息

//宽img->width//高img->height//大小,这个好像与实际大小不太相符,不是很清楚img->size

二. 图像基本运算

1.加减乘除

图形相加

void add() {    cout << "图片加法运算" << endl;    const char* imagename1 = "1_add.jpg";    const char* imagename2 = "2_add.jpg";    IplImage* img1 = cvLoadImage(imagename1);    IplImage* img2 = cvLoadImage(imagename2);    //获取两图片的最小宽、最小高    int min_width = min(img1->width, img2->width);    int min_height = min(img1->height, img2->height);    //cvSetImageROI设置感兴趣区域,在此处进行操作    cvSetImageROI(img1, CvRect(0, 0, min_width, min_height));    cvSetImageROI(img2, CvRect(0, 0, min_width, min_height));    //两图片相加    cvAddWeighted(img1, 0.5, img2, 0.5, 0.0, img1);    cvShowImage("图片相加", img1);    cvWaitKey(0);    //释放内存    cvReleaseImage(&img1);    //销毁窗口    cvDestroyWindow("图片相加");}

实验结果:

这里写图片描述 这里写图片描述 这里写图片描述 图像一 图像二 结果

图形相减

void sub() {    cout << "图片减法运算" << endl;    const char* imagename1 = "1_sub.jpg";    const char* imagename2 = "2_sub.jpg";    IplImage* img1 = cvLoadImage(imagename1);    IplImage* img2 = cvLoadImage(imagename2);    int min_width = min(img1->width, img2->width);    int min_height = min(img1->height, img2->height);    cvSetImageROI(img1, CvRect(0, 0, min_width, min_height));    cvSetImageROI(img2, CvRect(0, 0, min_width, min_height));    cout << "图片一:" << img1->width  << " " << img1->height << endl;    cout << "图片二:" << img2->width << " " << img2->height << endl;    //cvAddWeighted(img1, 0.5, img2, -0.5, 0.0, img1);    cvSub(img1, img2, img1);    cvShowImage("图片相减", img1);    cvWaitKey(0);    //释放内存    cvReleaseImage(&img1);    //销毁窗口    cvDestroyWindow("图片相减");}
这里写图片描述 这里写图片描述 这里写图片描述 图片一 图片二 结果

图像相乘

这里用的是二值蒙板图像与原图像相乘,为了实现一定的效果(去除背景),这里并没有直接使用opencv自带的乘法运算。而是对图像进行了遍历。如果二值蒙版图像在某像素处的值小于10,那么就将与图像在相同位置的值设为0,否则的话不变
void mul() {    cout << "图片乘法运算" << endl;    const char* imagename1 = "1_mul.jpg";    const char* imagename2 = "2_mul.jpg";    IplImage* img1 = cvLoadImage(imagename1);    IplImage* img2 = cvLoadImage(imagename2);    int min_width = min(img1->width, img2->width);    int min_height = min(img1->height, img2->height);    //cvSetImageROI(img1, CvRect(0, 0, min_width, min_height));    //cvSetImageROI(img2, CvRect(0, 0, min_width, min_height));    cout << "图片一:" << img1->width << " " << img1->height << endl;    cout << "图片二:" << img2->width << " " << img2->height << endl;    for (int i = 0; i < min_height; i ++) {        uchar* ptr = (uchar*)(img1->imageData + i* img1->widthStep);        uchar* ptr2 = (uchar*)(img2->imageData + i* img2->widthStep);        for (int j = 0; j < min_width; j++) {            if (ptr[3 * j] < 10)                ptr2[3 * j] = 0;            if (ptr[3 * j + 1] < 10)                ptr2[3 * j + 1] = 0;            if(ptr[3 *j + 2] < 10)                ptr2[3 * j + 2] = 0;            /*            if (ptr[3 * j] == 0) {                ptr2[3 * j] = ptr[3 * j + 1] = ptr[3 * j + 2] = 0;            }            */        }    }    //cvMul(img2, img1, img1);    cvShowImage("图片相乘", img2);    cvWaitKey(0);    //释放内存    cvReleaseImage(&img2);    //销毁窗口    cvDestroyWindow("图片相乘");}
这里写图片描述 这里写图片描述 这里写图片描述 图片一 图片二 结果

图像相除

void div() {    cout << "图片除法运算" << endl;    const char* imagename1 = "2_add.jpg";    const char* imagename2 = "3.jpg";    //const char* imagename1 = "1_mul.jpg";    //const char* imagename2 = "2_mul.jpg";    IplImage* img1 = cvLoadImage(imagename1);    IplImage* img2 = cvLoadImage(imagename2);    int min_width = min(img1->width, img2->width);    int min_height = min(img1->height, img2->height);    cvSetImageROI(img1, CvRect(0, 0, min_width, min_height));    cvSetImageROI(img2, CvRect(0, 0, min_width, min_height));    cout << "图片一:" << img1->width << " " << img1->height << endl;    cout << "图片二:" << img2->width << " " << img2->height << endl;    cvDiv(img2, img1, img2);    cvShowImage("图片相除", img2);    cvWaitKey(0);    //释放内存    cvReleaseImage(&img2);    //销毁窗口    cvDestroyWindow("图片相除");}
这里写图片描述 这里写图片描述 这里写图片描述 图片一 图片二 结果

2.图像灰度级变换

图像求反

void reverse() {    cout << "图片求反运算" << endl;    const char* imagename = "2_mul.jpg";    IplImage* img = cvLoadImage(imagename);    for (int i = 0; i < img->height; i++) {        uchar* ptr = (uchar*)(img->imageData + i* img->widthStep);        for (int j = 0; j < img->width; j++) {            ptr[3 * j] = 255 - ptr[3 * j];            ptr[3 * j + 1] = 255 - ptr[3 * j + 1];            ptr[3 * j + 2] = 255 - ptr[3 * j + i];        }    }    cvShowImage("图片求反", img);    cvWaitKey(0);    //释放内存    cvReleaseImage(&img);    //销毁窗口    cvDestroyWindow("图片求反");}
这里写图片描述 这里写图片描述 图片一 结果

3.图像变换

图像平移

void transform() {    cout << "图片平移" << endl;    const char* imagename = "2_add.jpg";    IplImage* img = cvLoadImage(imagename);    int dx, dy;    cout << "请输入平移的宽和高, 如:50 50" << endl;    cin >> dx >> dy;    int height = img->height;    int width = img->width;    IplImage* res = cvCreateImage(cvSize(width, height), img->depth, img->nChannels);    for (int i = 0; i < height; i++) {        int pos_x = i + dx;        if (pos_x < height && pos_x > -1) {            uchar* ptr = (uchar*)(img->imageData + i* img->widthStep);            uchar* ptr2 = (uchar*)(res->imageData + pos_x * res->widthStep);            for (int j = 0; j < width; j++) {                int pos_y = j + dy;                if (pos_y < width && pos_y > -1) {                    ptr2[3 * pos_y] = ptr[3 * j];                    ptr2[3 * pos_y + 1] = ptr[3 * j + 1];                    ptr2[3 * pos_y + 2] = ptr[3 * j + 2];                }            }        }    }    cvShowImage("图片平移", res);    cvWaitKey(0);    //释放内存    cvReleaseImage(&res);    //销毁窗口    cvDestroyWindow("图片平移");}
这里写图片描述 这里写图片描述 图片一 结果

图像缩放

这里输入图像宽和高的缩放倍数(> 0), 对图像进行放大和缩小

void zoom() {    cout << "图片缩放" << endl;    const char* imagename = "2_add.jpg";    IplImage* img = cvLoadImage(imagename);    float dx, dy;    cout << "请输入图片宽和高的放大倍数,如:1 0.5" << endl;    cin >> dx >> dy;    int height = img->height;    int width = img->width;    IplImage* res = cvCreateImage(cvSize(width*dx, height*dy), img->depth, img->nChannels);    //二维旋转的仿射变换矩阵      float m[6] = {dx, 0, 0, 0, dy, 0};    CvMat M = cvMat(2, 3, CV_32F, m);    //变换图像    cvWarpAffine(img, res, &M, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS);    cvShowImage("图片缩放", res);    cvWaitKey(0);    //释放内存    cvReleaseImage(&res);    //销毁窗口    cvDestroyWindow("图片缩放");}
这里写图片描述 这里写图片描述 图片1 结果

图像旋转

图像旋转后,会导致图像显示不全,这里图像旋转后,大小会发生变化,使图片能够显示完全

void rotate() {    cout << "图片旋转" << endl;    const char* imagename = "2_add.jpg";    IplImage* img = cvLoadImage(imagename);    int degree;    cout << "请输入图像旋转角度, 如:30" << endl;    cin >> degree;    double angle = degree  * CV_PI / 180.; // 弧度        double sina = sin(angle), cosa = cos(angle);    int height = img->height;    int width = img->width;    int width_rotate = int(height * fabs(sina) + width * fabs(cosa));    int height_rotate = int(width * fabs(cosa) + height * fabs(sina));    cout << width << " " << height << endl;    cout << width_rotate << " " << height_rotate << endl;    IplImage* res = cvCreateImage(cvSize(width_rotate, height_rotate), img->depth, img->nChannels);    //旋转中心     CvPoint2D32f center;    center.x = float(width / 2.0);    center.y = float(height / 2.0);    //二维旋转的仿射变换矩阵    float m[6];    //float m[6];    CvMat M = cvMat(2, 3, CV_32F, m);    cv2DRotationMatrix(center, degree, 1, &M);    m[2] += (width_rotate - width) / 2;    m[5] += (height_rotate - height) / 2;    //变换图像,其余值填充用白色    cvWarpAffine(img, res, &M, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(255));      cvShowImage("图片旋转", res);    cvWaitKey(0);    //释放内存    cvReleaseImage(&res);    //销毁窗口    cvDestroyWindow("图片旋转");}
这里写图片描述 这里写图片描述 图片1 结果

4.直方图均衡化处理

要求:自己编写函数,不能使用opencv自带函数(虽然我也不知道自带函数是什么…)

直方图均衡化是将原图像通过某种变换,得到一幅图像,整个图像灰度直方图为均匀分布的新图像的方法。

根据个人理解,直方图均衡化处理大致有如下步骤:

  1. 灰度直方图统计hist[0..L-1]: 图像有L灰度级(L=256,即8位灰度级),统计各个灰度级在图像中出现的次数,之后hist[]/=图像像素。
  2. 归一化累积直方图t[0..L-1]: 计算方式为t[x] = t[x-1] + s[x]
  3. 遍历图像,根据t[0..L-1],计算每一点新的像素值: f(x,y) = t[f(x,y)]*L
void equalization() {    cout << "直方图均衡化" << endl;    const char* imagename = "4.jpg";    IplImage* img = cvLoadImage(imagename);    double *hist = new double[256];    double *t = new double[256];    for (int i = 0; i < 256; i++) {        hist[i] = 0;        t[i] = 0;    }    for (int i = 0; i < img->height; i++) {        uchar* ptr = (uchar*)(img->imageData + i* img->widthStep);        for (int j = 0; j < img->width; j++) {            hist[ptr[3 * j]]++;            hist[ptr[3 * j + 1]]++;            hist[ptr[3 * j + 2]]++;        }    }    int result = img->width*img->height*3;    t[0] = hist[0]/result;    for (int i = 1; i < 256; i++) {         t[i] = t[i - 1] + (double)(hist[i]/result);    }    for (int i = 0; i < img->height; i++) {        uchar* ptr = (uchar*)(img->imageData + i* img->widthStep);        for (int j = 0; j < img->width; j++) {            ptr[3 * j] = t[ptr[3*j]]*255;            ptr[3 * j + 1]=t[ptr[3*j + 1]]*255;            ptr[3 * j + 2]=t[ptr[3*j + 2]]*255;        }    }    cvShowImage("直方图均衡化", img);    cvWaitKey(0);    //释放内存    cvReleaseImage(&img);    //销毁窗口    cvDestroyWindow("直方图均衡化");}
这里写图片描述 这里写图片描述 原图片 增强后图片
0 0
原创粉丝点击