计算机图形图像实验
- 计算机图形图像实验
- 一 图像处理初步
- 二 图像基本运算
- 加减乘除
- 图像灰度级变换
- 图像变换
- 直方图均衡化处理
一. 图像处理初步
1. opencv安装,配置
VS配置opencv时,要修改三个地方,如下图
2.图像读取与显示
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(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;
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);
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;
}
}
cvShowImage("图片相乘", img2);
cvWaitKey(0);
cvReleaseImage(&img2);
cvDestroyWindow("图片相乘");
}
图像相除
void div() {
cout << "图片除法运算" << endl;
const char* imagename1 = "2_add.jpg";
const char* imagename2 = "3.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];
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自带函数(虽然我也不知道自带函数是什么…)
直方图均衡化是将原图像通过某种变换,得到一幅图像,整个图像灰度直方图为均匀分布的新图像的方法。
根据个人理解,直方图均衡化处理大致有如下步骤:
- 灰度直方图统计hist[0..L-1]: 图像有L灰度级(L=256,即8位灰度级),统计各个灰度级在图像中出现的次数,之后hist[]/=图像像素。
- 归一化累积直方图t[0..L-1]: 计算方式为t[x] = t[x-1] + s[x]
- 遍历图像,根据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("直方图均衡化");
}
|
|
原图片 |
增强后图片 |