本节主要涉及到图像的领域、算术操作以及如何操作图像感兴趣的区域。

一:邻域操作

以下例子主要对图像进行锐化。基于拉普拉斯算子<后面讨论>。这幅图像的边缘部分将得到放大,细节部分将更加的锐利。计算方式为:

sharpened_pixel = 5*current – left – right –up – down.

Code:

#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\core\core.hpp>
#include <iostream> using namespace std;
using namespace cv; void sharpen(const Mat &image, Mat &result)
{
const int nChannels = image.channels();
for(int j = 1; j < image.rows - 1; j++)
{
const uchar *previous = image.ptr<const uchar>(j-1); // 上一行
const uchar *current = image.ptr<const uchar>(j); // 此行
const uchar *next = image.ptr<const uchar>(j+1); //下一行
uchar *output = result.ptr<uchar>(j); for(int i = 1; i < image.cols - 1; i++)
{
if(image.channels() == 1) // 黑白图像
{
output[i] = saturate_cast<uchar>(5*current[i] - current[i-1] - current[i+1] - previous[i] - next[i]);
}
else if(image.channels() == 3) // 彩色图像
{
*(output + i*image.elemSize()) =saturate_cast<uchar>(5 * *(current + i*image.elemSize()) - *(current + (i-1)*image.elemSize())- *(current + (i+1)*image.elemSize()) - *(previous + i*image.elemSize())- *(next + i*image.elemSize()));
*(output + i*image.elemSize() + 1) = saturate_cast<uchar>(5 * *(current + i*image.elemSize() + 1) - *(current + (i-1)*image.elemSize() + 1)- *(current + (i+1)*image.elemSize() + 1) - *(previous + i*image.elemSize() + 1)- *(next + i*image.elemSize() + 1));
*(output + i*image.elemSize() + 2) = saturate_cast<uchar>(5 * *(current + i*image.elemSize() + 2) - *(current + (i-1)*image.elemSize() + 2)- *(current + (i+1)*image.elemSize() + 2) - *(previous + i*image.elemSize() + 2)- *(next + i*image.elemSize() + 2));
} }
/*for(int i = nChannels; i < nChannels * (image.cols - 1); ++i)
{
*output ++ = saturate_cast<uchar>(5*current[i] - current[i-nChannels] - current[i+nChannels] - previous[i] - next[i]); }*/
}
result.row(0).setTo(Scalar(0));
result.row(result.rows - 1).setTo(Scalar(0));
result.col(0).setTo(Scalar(0,0,0));
result.col(result.cols - 1).setTo(Scalar(0));
return;
} void sharpen2D(const Mat &image, Mat &result)
{
Mat kernel(3, 3, CV_32FC1, Scalar(0));
kernel.at<float>(1,1) = 5.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;
/*也可以这样定义,这是opencv中简单初始化只有几个像素的mat类型*/
//Mat kernel = (Mat_<float>(3,3) << 0, -1.0, 0.0, -1.0, 5.0, -1.0, 0, -1.0, 0);
filter2D(image, result,image.depth(), kernel);
return;
}
int main()
{
Mat image = imread("F:\\huangrong.jpg", 0);
Mat result;
cout << image.depth() << endl;
result.create(Size(image.cols, image.rows), image.type());
sharpen(image, result);
//sharpen2D(image, result);
namedWindow("image");
imshow("image", image);
namedWindow("result");
imshow("result", result);
waitKey(0);
return 0;
}

Explaination:

(1)  saturate_cast<uchar>主要是类型检查来保证转换的安全性。如对于计算得到的结果不在0~255范围内,则进行截断。通常做法是将负值截断为0,将大于255的截断为255.

(2)  Matkernel = (Mat_<float>(3,3) << 0, -1.0, 0.0, -1.0, 5.0, -1.0, 0,-1.0, 0);

//opencv中简单初始化只有几个像素的mat类型

(3)  result.row(0).setTo(Scalar(0));

//可以将矩阵的第0行所有像素全部设置为0

(4)opencv中自带了filter2D这个函数可以进行领域操作,其结果是一样的,在某些情况下回更高效点。

Result:

二:算术操作

Code:

#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <iostream> using namespace std;
using namespace cv; Mat addWeight(Mat &image, Mat &image2)
{
Mat result;
//addWeighted(image, 0.5, image2, 0.5, 0.0, result);
result = image*0.5 + image2*0.5 + 0.3; // 大多数算术函数在opencv2中都有对应的重载操作符
return result;
} Mat addWeight2(Mat &image, Mat &image3)
{
Mat result;
vector<Mat> planes;
split(image, planes); /// 将一个彩色三通道图像分解为三个单通道图像
planes[0] += image3;
merge(planes, result); /// 将三个单通道图像合并为一个彩色三通道图像
return result;
} int main()
{
Mat image = imread("F:\\huangrong.jpg", 1);
if(!image.data){
cout << "fail to load image" << endl;
return 0;
}
Mat image2 =Mat::zeros(image.rows, image.cols, image.type());
//Mat image2(image.rows, image.cols, image.type(), Scalar(255, 255, 255));
Mat result;
result = addWeight(image, image2); Mat result2;
Mat image3 = Mat::zeros(image.rows, image.cols, CV_8UC1);
result2 = addWeight2(image, image3);
namedWindow("image");
imshow("image", image);
namedWindow("image2");
imshow("image2", image2);
namedWindow("result");
imshow("result", result);
namedWindow("result2");
imshow("result2", result2);
waitKey(0);
return 0;
}

Explaination:

(1)  以上实现的是两幅图像相加,即可用opencv自带的函数addWeighted,也可用重载的运算符+。其它如&,|,^,~等都被重载了。除了加法,还有其它运算,如矩阵求逆m1.inv(),装置m1.t(),矩阵行列式m1.determinant()等

(2)  split(image, planes);和merger(planes,image); 分别是将一个彩色三通道图像分解为三个单通道图像和将三个单通道图像合并为一个彩色三通道图像

Result:

三:定义感兴趣区域

Code:

#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <iostream> using namespace std;
using namespace cv; int main()
{
Mat image = imread("F:\\huangrong.jpg", 1);
if(!image.data){
cout << "fail to load image" << endl;
return 0;
}
Mat tongtong = imread("F:\\tt.png", 1);
//Mat imageROI = image(Rect(140,20,tongtong.cols, tongtong.rows));
//Mat imageROI(image, Rect(140,20,tongtong.cols, tongtong.rows));//第二种方式
Mat imageROI = image(Range(20, 20 + tongtong.rows),Range(140, 140+tongtong.cols)); // 第三种方式
tongtong.copyTo(imageROI);
namedWindow("imageROI");
imshow("imageROI", imageROI);
namedWindow("image");
imshow("image",image);
waitKey(0);
return 0;
}

Explaination:

(1)  三种方式:

a)       MatimageROI = image(Rect(140,20,tongtong.cols, tongtong.rows));

b)       MatimageROI(image, Rect(140,20,tongtong.cols, tongtong.rows));

c)       MatimageROI = image(Range(20, 20 + tongtong.rows),Range(140, 140+tongtong.cols));  // 其中Range是指从起始索引到终止索引(不包含终止索引)的一段连续序列。

(2)其中需要注意的是:ROI和原始图像共享数据缓冲区,对ROI的任何变换都会影响到图像对应的区域。

作者:小村长  出处:http://blog.csdn.net/lu597203933 欢迎转载或分享,但请务必声明文章出处。 (新浪微博:小村长zack, 欢迎交流!)

Opencv2系列学习笔记2(图像的其它操作)的更多相关文章

  1. Opencv2系列学习笔记8(图像滤波)

    一:概念: 滤波是信号处理机图像处理中的一个基本操作.滤波去除图像中的噪声,提取感兴趣的特征,允许图像重采样. 图像中的频域和空域:空间域指用图像的灰度值来描述一幅图像:而频域指用图像灰度值的变化来描 ...

  2. opencv学习笔记(五)----图像的形态学操作

    图像的形态学操作有基本的腐蚀和膨胀操作和其余扩展形态学变换操作(高级操作)-----开运算,闭运算,礼帽(顶帽)操作,黑帽操作...(主要也是为了去噪声,改善图像) 形态学操作都是用于处理二值图像(其 ...

  3. Opencv2系列学习笔记10(提取连通区域轮廓)

    连通区域指的是二值图像中相连像素组成的形状.而内.外轮廓的概念及opencv1中如何提取二值图像的轮廓见我的这篇博客:http://blog.csdn.net/lu597203933/article/ ...

  4. Opencv2系列学习笔记10(提取连通区域轮廓) 另一个

    http://blog.csdn.net/lu597203933/article/details/17362457 连通区域指的是二值图像中相连像素组成的形状.而内.外轮廓的概念及opencv1中如何 ...

  5. OpenCV2计算机编程手册(一)操作像素

    1. 引言 从根本上来说,一张图像是一个由数值组成的矩阵.这也是opencv中使用 代表黑色,代表白色.对于彩色图像(BGR三通道)而言,每个像素需要三个这样的8位无符号数来表示,这种情况下,矩阵的元 ...

  6. MVA Universal Windows Apps系列学习笔记1

    昨天晚上看了微软的Build 2015大会第一天第一场演讲,时间还挺长,足足3个小时,不过也挺震撼的.里面提到了windows 10.Microsoft edge浏览器.Azure云平台.Office ...

  7. opencv-学习笔记(6)图像梯度Sobel以及canny边缘检测

    opencv-学习笔记(6)图像梯度Sobel以及canny边缘检测 这章讲了 sobel算子 scharr算子 Laplacion拉普拉斯算子 图像深度问题 Canny检测 图像梯度 sobel算子 ...

  8. Caffe学习笔记4图像特征进行可视化

    Caffe学习笔记4图像特征进行可视化 本文为原创作品,未经本人同意,禁止转载,禁止用于商业用途!本人对博客使用拥有最终解释权 欢迎关注我的博客:http://blog.csdn.net/hit201 ...

  9. OpenCV2:第六章 图像几何变换

    一.简介 图像的几何变换有距离变换 坐标映射 平移  镜像 旋转  缩放  仿射变换等 二.重映射 把一张图像重新排列像素,比如倒置 CV_EXPORTS_W void remap( InputArr ...

随机推荐

  1. hive 分区操作记录

    创建分区: alter table table_name add partition (dt='20150423') location '/data/text/20150423';

  2. iphone手机上的click和touch

    在iphone手机上绑定click事件时,当你触发点击事件时,你绑定的click事件的DOM节点,会自动被一块浮层选中.所以如果使用事件委托来做事件绑定会造成很差的用户体验. 使用touchstart ...

  3. [LeetCode]题解:005-Longest Palindromic Substring优化

    题目来源和题意分析: 详情请看我的博客:http://www.cnblogs.com/chruny/p/4791078.html 题目思路: 我上一篇博客解决这个问题的时间复杂度是最坏情况是(O(n^ ...

  4. Spring RESTful服务接收和返回JSON最佳实践

    http://blog.csdn.net/prince_hua/article/details/12103501

  5. PHP glob() 函数用法

    glob() 函数返回匹配指定模式的文件名或目录. 该函数返回一个包含有匹配文件 / 目录的数组.如果出错返回 false. 语法 array glob ( string $pattern [, in ...

  6. ThinkPHP 3.1.2 模板中的变量

    一.变量输出 (重点) 1.标量输出 2.数组输出 {$name[1]} {$name['k2']} {$name.k1} 3.对象输出 {$name:k} {$name->k} 二.系统变量 ...

  7. perl5 第一章 概述

    第一章 概述 by flamephoenix 一.Perl是什么?二.Perl在哪里?三.运行四.注释 一.Perl是什么?      Perl是Practical Extraction and Re ...

  8. C++中struct和class的总结

    一.在语法上的一些区别 由于C++是从C发展而来,C++中的struct更多的是去做了兼容的C的部分.在语法层面他们有以下的区别: 1. struct中所有的成员是是public,也就是说你可以对一个 ...

  9. 用git上传项目到github

    1 git  clone  github仓库地址 2 git add . 3 git  commit -m "changes log" 4 git remote add origi ...

  10. Android 性能优化 三 布局优化ViewStub标签的使用

    小黑与小白的故事,通过虚拟这两个人物进行一问一答的形式来共同学习ViewStub的使用 小白:Hi,小黑,ViewStub是什么?听说能够用来进行布局优化. 小黑:ViewStub 是一个隐藏的,不占 ...