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

一:邻域操作

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

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. 城通网盘,千军万马,千脑网盘,119g网盘哪个适合做网赚?

    转载请注明文章来自 [ofiicexie] 网盘网赚已经流行了有一段时间了,国内流行的几个网盘有城通,千军万马,千脑,119g,今天小编写以此文来比较分析一下这几个网盘的优缺点. 这里,我特意做了个这 ...

  2. Qt在Linux环境下应用程序字体模糊的解决方法(先改成使用默认字体,然后使用qtconfig配置)

    这两天一直在用Qt实现一个跨平台的软件.软件之前在Windows上编写的,后来放到里Ubuntu 10.10下编译.程序运行时遇到一个很棘手的问题,界面文本非常模糊.后来在网上查阅了好几天的资料,经历 ...

  3. FMX相当于在界面上自己又做了一个小操作系统

    FMX的自画界面我也不看好,比如复制粘贴,太丑了,系统做得很好很精细的复制粘贴界面,就是无法调出,比如MIUI,复制粘贴还能有个放大镜,可以选择到屏幕边缘的文字,可以选择剪贴板内多个可粘贴的文字:还有 ...

  4. android studio 快捷笔记

    setting->editor->打勾 ctrl+Q ctrl+tab alt+回车 ctrl+shift+回车

  5. Linux设置高分辨率后无法进入X系统

    Vmware9.0中Xubuntu分辨率从800x600变更为1366x768后在用户输入密码登录后会自动退出x系统,出现这种情况时可以切换到命令行登录界面,然后将-/.config/xfce4/xf ...

  6. JAVA GUI学习 - JOptionPane对话框组件学习

    /** * 对话框 - 学习笔记 * @author Wfei * */ public class JoptionPaneKnow extends JFrame { public JoptionPan ...

  7. 算法导论 6.5.9 堆实现K路归并问题

    问题: 设计一个时间复杂度为O(NlogK)的算法,它能够将K个有序链表合并为一个有序链表,这里的N为所有输入链表包含的总的元素个数 分析: 该问题为经典的利用堆完成K路归并的问题: 当K个序列满足一 ...

  8. linux内核源码阅读之facebook硬盘加速flashcache之二

    flashcache数据结构都在flashcache.h文件中,但在看数据结构之前,需要先过一遍flashcache是什么,要完成哪些功能?如果是自己设计这样一个系统的话,大概要怎么设计. 前面讲过, ...

  9. 使用mongodb存取lbs数据

    1,在mongodb中创建lbs_db数据库,collection名称lbs_info,要使用lbs查询功能,需要对二维数据列建立索引 db.lbs_info.ensureIndex( { locs ...

  10. Unity的NGUI插件篇——入场效果

    Unity的NGUI插件篇--入场效果 入场效果 入场效果须要借助于NGUI提供的TweenPosition类来完毕.为了说明此类的用法.本节将使会解说两个演示样例.本文选自  大学霸 <NGU ...