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

一:邻域操作

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

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. JQuery中文本框获取焦点

    今天遇见这么一个小小的问题,就是文本框中需要输入内容才可以提交,如果没有输入就提示并使该文本框获得焦点! 这么一个简单的事情如果没有使用jQuery的话 是不是对象.focus()就可以了, 可是当我 ...

  2. C语言(2)--数据类型

    C语言中提供多种不同的数据类型,用以存放不同的数据. 1.常见的基本类型有:int-->整型 float-->浮点型 double-->双精度浮点型 char-->字符型 NO ...

  3. Array.Add () and += in PowerShell

    $newArray = @() $newArray.Add("Hello") If I create a new array, and using the method Add() ...

  4. IOS 学习笔记(6) 控件 文本域(UITextField)的使用方法

    UITextField控件的诸多特性都和UITextView相似,比如成为输入文本焦点时键盘自动显示,支持长按弹出动作选项,能够接收输入事件(开始输入,修改内容,结束输入和点击回车等). 1.特有的特 ...

  5. viewpager的layout_width="wrap_content"无效问题

    在viewpager当中直接使用layout_width="wrap_content"是无效的,扩展了一下.解决这个问题. package com.soulagou.ui; imp ...

  6. Hello China操作系统STM32移植指南(三)

    移植到STM32的源代码,可从下列链接下载: http://download.csdn.net/detail/hellochina15/7049909 包含两个包:一个是移植前的Hello China ...

  7. PLSQL 导入表到Oracle------》从一个表空间导入到其它表空间

        在用PLSQL导入.dmp文件到Oracle时出现的问题如下: Import started on 2015/11/18 10:42:44E:\oracle\product\10.2.0\db ...

  8. POJ1797 Heavy Transportation 【Dijkstra】

    Heavy Transportation Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 21037   Accepted:  ...

  9. android基础篇------------java基础(12)(多线程操作)

    <一>基本概念理解 1.什么是进程? 进程就是在某种程度上相互隔离,独立运行的程序.一般来说,系统都是支持多进程操作的,这所谓的多进程就是让系统好像同时运行多个程序. 2.什么是线程呢? ...

  10. asp.net Page_Load事件加载两次

    Page_Load 即使加上 if(!IsPostBack){ ……} 还时走了2次 这时候 或者看看你的程序和脚本,是不是刷新页面了 或者页面的样式有错误的地方  例如: background:ur ...