近来给自己开个新坑,打算学习下OpenCV这一计算机视觉库。
参考资料:《OpenCV 2 计算机视觉 编程手册》
【以下内容默认版本OpenCV 2.3.1】
最简单的操作莫过于对于一张图片上的像素的遍历了,然而,遍历的方式有很多种,如何取舍很是关键。
简单介绍几种常见的方式:
1.指针遍历:
int row = image.rows; int col = image.cols * image.channels(); for(int i = 0; i < row; i++) { uchar* data = image.ptr<uchar>(i); for(int j = 0; j < col; j++) { ... } }
基于以上这点特性,我们可以得到如下改进版:
int row = image.rows; int col = image.cols * image.channels(); if(image.isContinuous()) { //判断有没有额外补充像素 col = col * row; row = 1; } for(int i = 0; i < row; i++) { uchar* data = image.ptr<uchar>(i); for(int j = 0; j < col; j++) { ... } }
2.迭代器遍历:
迭代器通过隐藏内部实现方式的方法,提供了相对通用且普遍的使用方法。大大提升了代码的可读性。
cv::Mat_<cv::Vec3b>::iterator it = image.begin<cv::Vec3b>(); cv::Mat_<cv::Vec3b>::iterator itend = image.end<cv::Vec3b>(); for(; it != itend; ++it) { ... }在遍历的过程中,由于处理的是彩色图像,我们可以通过操作符[]来访问,如(*it)[0]和(*it)[2]。
于是乎,我们在get遍历技能之后,就可以简单的实现一些如图片锐化的基础操作了。下面附上一下我基于控制台的代码,以及一张简单的效果示例图。
#include <opencv2\opencv.hpp> #include <iostream> #include <string> #include <stdio.h> using namespace std; using namespace cv; /*-------------------添加椒盐噪点---------------------*/ void salt(const cv::Mat &input, cv::Mat &output, int n) { input.copyTo(output); int col = output.cols; int row = output.rows; int channel = output.channels(); for(int i = 0; i < n; i++) { int x = rand() % row; int y = rand() % col; if(channel == 1) { output.at<uchar>(x, y) = 0; } else { output.at<cv::Vec3b>(x, y)[0] = 0; output.at<cv::Vec3b>(x, y)[1] = 0; output.at<cv::Vec3b>(x, y)[2] = 0; } } } /*-------------------颜色缩减函数---------------------*/ void colorReduce(const cv::Mat &input, cv::Mat &output, int div = 64) { if(input.isContinuous()) { input.reshape(1, input.cols * input.rows); } int row = input.rows; int nc = input.cols * input.channels(); for(int i = 0; i < row; i++) { const uchar* data_in = input.ptr<uchar>(i); uchar* data_out = output.ptr<uchar>(i); for(int j = 0; j < nc; j++) { data_out[j] = data_in[j] / div * div + div / 2; } } } /*-------------------颜色缩减函数---------------------*/ void sharpen2D(const cv::Mat &input, cv::Mat &output) { //构造核(并将其他项初始化为0) cv::Mat kernel(3, 3, CV_32F, cv::Scalar(0)); //对核元素进行赋值 kernel.at<float>(0, 1) = -1.0; kernel.at<float>(1, 0) = -1.0; kernel.at<float>(1, 2) = -1.0; kernel.at<float>(2, 1) = -1.0; kernel.at<float>(1, 1) = 5.0; //对图像进行滤波 cv::filter2D(input, output, input.depth(), kernel); } /*-------------------添加水印函数---------------------*/ void getWaterMark(cv::Mat &logo, cv::Mat &output) { //定义图像ROI cv::Mat imageROI; int row = output.rows, col = output.cols; int logo_row = logo.rows, logo_col = logo.cols; if(row < logo_row || col < logo_col) { puts("logo过大或图片过小,水印加载失败"); return ; } imageROI = output(cv::Rect(col - logo_col, row - logo_row, logo_col, logo_row)); //加载掩模, 并插入logo logo.copyTo(imageROI, logo); } /*--------------------主 函 数----------------------*/ int main() { std::string str; cv::Mat output; puts("输入图片名称,含文件后缀名部分:"); cin >> str; cv::Mat input = cv::imread(str); if(input.empty()) { cout<< "error" << endl; return -1; } cout << "已成功打开图片, 图片的大小为 : "; cout << input.size().width << " * " << input.size().height << "像素." << endl; int type; int vis[10] = {0}; cout << "1.显示原图像" << endl; cout << "2.增加椒盐噪点" << endl; cout << "3.颜色缩减" << endl; cout << "4.图像锐化" << endl; cout << "5.添加logo" << endl; cout << "6.显示当前修改图像" << endl; cout << "0.退出" << endl; while(true) { cout << "请输入您需要的操作序号(按Enter键结束):" << endl; cin >> type; if(type < 0 || type > 6) { cout << "无效操作" << endl; continue; } if(vis[type]) { cout << "该操作已经执行过,请尝试其他功能" << endl; } else vis[type] = 1; if(type == 1) { cv::imshow("原图像", input); cv::waitKey(); } else if(type == 2) { salt(input, output, 3000); } else if(type == 3) { colorReduce(input, output); } else if(type == 4) { sharpen2D(input, output); } else if(type == 5) { bool exist = false; for(int i = 1; i <= 6; i++) { if(i == 5) continue; else if(vis[i]) exist = true; } if(!exist) { cout << "当前输出图片不存在" << endl; vis[type] = false; continue; } cv::Mat logo = cv::imread("gx_logo.png"); getWaterMark(logo, output); } else if(type == 6) { cv::namedWindow("dog"); cv::imshow("dog", output); cv::waitKey(); } else if(type == 0) { break; } } cv::imwrite("haha.bmp", output); puts("运行结束"); system("pause"); return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/gaoxiang36999/article/details/48054843