图像像素操作
来源:互联网 发布:由于网络原因上传失败 编辑:程序博客网 时间:2024/06/04 23:24
访问像素值
为了访问 代码中指定元素所在的行和列。程序会返回相应的元素。如果是单通道的图像,返回值是单个数值;如查多通道的图像,返回值则是一组向量。
实现方法
我们创建一个椒盐现象的函数,第一个参数是一张输入图像,第二个参数是我们欲将其替换成白色像素点的像素点个数。
- void salt(cv::Mat &img, int n){
- for( int k = 0; k < n; k++){
- int i = rand()%img.cols;
- int j = rand()%img.rows;
- if(img.channels( ) == 1){
- img.at<uchar>(j,i) = 255;
- }
- else if(img.channels( ) == 3){
- img.at<cv::Vec3b>(j,i)[0] =255;
- img.at<cv::Vec3b>(j,i)[1] =255;
- img.at<cv::Vec3b>(j,i)[2] =255;
- }
- }
- }
- cv::Mat img = cv::imread("../../../waves.jpg");
- salt(img,3000);
- cv::namedWindow("Salt Window");
- cv::imshow("Salt Window",img);
完整代码:
C++版
- // salt_image.cpp : Defines the entry point for the console application.
- #include "stdafx.h"
- #include <Opencv2\opencv.hpp>
- void salt(cv::Mat &img, int n){
- for( int k = 0; k < n; k++){
- int i = rand()%img.cols;
- int j = rand()%img.rows;
- if(img.channels( ) == 1){
- img.at<uchar>(j,i) = 255;
- }
- else if(img.channels( ) == 3){
- img.at<cv::Vec3b>(j,i)[0] =255;
- img.at<cv::Vec3b>(j,i)[1] =255;
- img.at<cv::Vec3b>(j,i)[2] =255;
- }
- }
- }
- int _tmain(int argc, _TCHAR* argv[]){
- cv::Mat img = cv::imread("../../../waves.jpg");
- if(img.data){
- salt(img,3000);
- cv::namedWindow("Salt Window");
- cv::imshow("Salt Window",img);
- cv::waitKey(0);
- cv::destroyAllWindows()
- }
- else
- printf("Open Image is Error!");
- return 0;
- }
- import cv2
- import numpy as np
- def salt(img, n):
- for k in range(n):
- i = int(np.random.random() * img.shape[1]);
- j = int(np.random.random() * img.shape[0]);
- if img.ndim == 2:
- img[j,i] = 255
- elif img.ndim == 3:
- img[j,i,0]= 255
- img[j,i,1]= 255
- img[j,i,2]= 255
- return img
- if __name__ == '__main__':
- img = cv2.imread("../waves.jpg")
- saltImage = salt(img, 3000)
- cv2.imshow("Salt", saltImage)
- cv2.imwrite("../wavessalt.jpg",saltImage)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
使用指针访问
我们在大多数的图像处理中,为了计算,需要遍历图像的所有像素。考虑到将要访问的像素个数非常之多,高效地遍历图像时非常重要的。
实现方法
首先我们定义一个颜色缩减函数原型如下:
- void colorReduce(cv::Mat &img,int div =64);
- void colorReduce( cv::Mat &img, int div =32){
- int nl =img.rows;
- int nc = img.cols*img.channels();
- for(int j =0; j< nl; j++){
- uchar* data = img.ptr<uchar>(j);
- for(int i=0; i<nc;i++){
- data[i] =data[i]/div*div+div/2;
- }
- }
- }
- cv::Mat img = cv::imread("../../../waves.jpg");
- colorReduce(img);
- cv::namedWindow("Reduce Window");
- cv::imshow("Reduce Window",img);
完整代码
- // Reduce_image.cpp : Defines the entry point for the console application.
- #include "stdafx.h"
- #include <Opencv2\opencv.hpp>
- void colorReduce( cv::Mat &img, int div =32){
- int nl =img.rows;
- int nc = img.cols*img.channels();
- for(int j =0; j< nl; j++){
- uchar* data = img.ptr<uchar>(j);
- for(int i=0; i<nc;i++){
- data[i] =data[i]/div*div+div/2;
- }
- }
- }
- int _tmain(int argc, _TCHAR* argv[]){
- cv::Mat img = cv::imread("../../../waves.jpg");
- colorReduce(img);
- cv::imwrite("Reduce.jpg",img);
- cv::namedWindow("Reduce Window");
- cv::imshow("Reduce Window",img);
- cv::waitKey(0);
- cv::destroyAllWindows();
- return 0;
- }
扩展知识
本例中提供的中是颜色缩减函数的一种实现方式,不必局限于此,可以使用其它的颜色缩减公式。我们也可以实现一个更通用的版本,它允许用户分别指定输入和输出图像。另外,图像遍历过程还可以通过利用图像数据的连续性,使得整个过程更高效。
1.其他的颜色缩减公式
我们可以选择使用位运算。
- //mask used to round the pixel value
- uchar maks = 0xFF<<n; // e.g. for dive =16, mask =0xF0
- data[i] =(data[i]&mask) +div/2
考虑到效率,图像有可能会在行尾扩大若干个像素。但是,值得注意的是当不对行进行填补的时候,图像可以被视为一个长为WxH的一维数组。我们可以通过OpenCV中的CV::Mat的一个成员函数 isContinuous来判断这幅图像是否对行进行了填补。重写颜色缩减函数为
- void colorReduce( cv::Mat &img, int div =32){
- if(img.isContinuous()){
- img.reshape(1,img.cols*img.rows);
- }
- int nl =img.rows;
- int nc = img.cols*img.channels();
- for(int j =0; j< nl; j++){
- uchar* data = img.ptr<uchar>(j);
- for(int i=0; i<nc;i++){
- data[i] =data[i]/div*div+div/2;
- }
- }
- }
3.底层的指针运算
在类 CV::Mat中,图像数据以unsigned char形成保存在一块内存中。即:
- uchar *data= img.data;
- data =+img.step;
- data =img.data +j*img.step+i*img.elemSize();
但是,即使这种方式确实行之有效,但容易出错。
迭代器遍历
在面对象的编程中,遍历数据集合通常是通过迭代器完成的。所以,我们将重写颜色缩减函数为:
- void colorReduce( cv::Mat &img, int div =32){
- cv::Mat_<cv::Vec3b>::iterator it = img.begin<cv::Vec3b>();
- cv::Mat_<cv::Vec3b>::iterator itend = img.end<cv::Vec3b>();
- for(; it!=itend; ++it){
- (*it)[0] =(*it)[0]/div*div +div/2;
- (*it)[1] =(*it)[1]/div*div +div/2;
- (*it)[2] =(*it)[2]/div*div +div/2;
- }
- }
遍历图像和邻域操作
在图像处理中,通过当前位置的相邻像素计算新的像素值是很常见的操作。当邻域包含图像的前几行和下几行时,你就需要同时扫描图像的若干行。本例子可以展示如何做到这一点。
- void sharpen(const cv::Mat &img,cv::Mat &result){
- result.create(img.size(),img.type());
- for(int j =1; j<img.rows-1;j++){
- const uchar* previous = img.ptr<const uchar>(j-1);
- const uchar* current = img.ptr<const uchar>(j);
- const uchar* next = img.ptr<const uchar>(j+1);
- const uchar* output = result.ptr<const uchar>(j);
- for(int i =1; i<img.cols-1;i++){
- *output++= cv::saturate_cast<uchar>(
- 5*current[i]-current[i-1]
- -current[i+1]-previous[i]-next[i]);
- }
- }
- result.row(0).setTo(cv::Scalar(0));
- result.row(result.rows-1).setTo(cv::Scalar(0));
- result.col(0).setTo(cv::Scalar(0));
- result.col(result.rows-1).setTo(cv::Scalar(0));
- }
From:http://blog.csdn.net/songzitea/article/details/8481443
0 0
- 快速图像像素操作
- android 操作图像像素
- 图像像素操作
- OpenGL: 图像像素操作
- 图像像素操作
- 图像像素操作
- 图像像素操作
- 图像的像素点操作
- opencv3/C++图像像素操作
- BGRABitmap图像操作4:直接操作像素
- android学习笔记之图像像素操作
- C# 操作图像像素 变灰 画图
- opencv对图像像素进行操作
- MAT型图像的像素操作
- OpenCV图像像素操作及效率分析
- OpenCV图像像素操作及效率分析
- 对图像的单个像素操作
- cuda中对图像像素的操作
- Unity3D技术之多玩家联网游戏创建说明
- table表头列头固定(css实现)
- 快速排序的非递归实现(栈)
- 集合框架篇2 Collection
- Java中的==和equals区别
- 图像像素操作
- Swing动画之敌机工厂
- 《linux命令行大全》读书笔记 第六章 重定向
- iOS开发中不可错过的十大第三方类库
- cocos2d-x环境搭建 window+eclipse+ndk
- UVA - 10057 A mid-summer night's dream.
- 题目1554:区间问题
- 用Python开始机器学习(4:KNN分类算法)
- SharePoint 2013 REST 服务使用简介