【OpenCV学习笔记】之访问图像的像素与ROI感兴趣区域选取

一、图像像素的操作

访问图像像素值是图像处理的基本操作。OpenCV提供了很多访问方式,比较常用的三种方式: 
(1) 通过指针访问 
(2) 通过迭代器访问 
(3) 动态地址计算,通过at()函数实现

方法比较: 
(1)用指针访问像素,速度最快;但在彩色图像处理中,如果要单独对某一个颜色分量处理,则需要通过数学公式计算,不是很直观; 
(2)推荐用通过迭代器访问像素,速度快,而且提取BGR某一颜色分量很方便。 
(3)at()函数适用于随机访问某个具体的像素点(已知该像素点行、列坐标),不建议用at()函数遍历整个图。

示例程序:

//对图像的像素值进行操作,三种方法:
#include "stdafx.h"
#include<opencv2/opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;


int main(int argc, char** argv)
{
	Mat src, gray_src;
	src = imread("C:/Users/59235/Desktop/image/flower.bmp");
	if (src.empty())
	{
		cout << "could not load image...\n" << endl;
		return -1;
	}
	namedWindow("input", CV_WINDOW_AUTOSIZE);
	imshow("input", src);

	cvtColor(src, gray_src, COLOR_BGR2GRAY);
	//namedWindow("output", CV_WINDOW_AUTOSIZE);
	//imshow("output", gray_src);

	int height = gray_src.rows;// int表示整型变量,是一种数据类型,用于定义一个整型变量
	int width = gray_src.cols;

	//方法一:使用动态地址计算
	//单通道:灰度图像
	int gray = gray_src.at<uchar>(Point(300, 300));
	printf("height:%d\n", height);
	printf("gray:%d\n", gray);
	for (int row = 0; row < height; row++)
	{
		for (int col = 0; col < width; col++)
		{
			int gray = gray_src.at<uchar>(row, col);
			gray_src.at<uchar>(row, col) = 255 - gray;
		}
	}
	
	//三通道:彩色图像RGB
	Mat dst;
	dst.create(src.size(), src.type());
	height = src.rows;
	width = src.cols;
	int nc = src.channels();
	printf("channels=%d\n", nc);
	for (int row = 0; row < height; row++)
	{
		for (int col = 0; col < width; col++)
		{
			if (nc == 1)
			{
				int gray = gray_src.at<uchar>(row, col);
				gray_src.at<uchar>(row, col) = 255 - gray;
			}
			else
			{
				int b = src.at<Vec3b>(row, col)[0];
				int g = src.at<Vec3b>(row, col)[1];
				int r = src.at<Vec3b>(row, col)[2];
				dst.at<Vec3b>(row, col)[0] = 255 - b;
				dst.at<Vec3b>(row, col)[1] = 255 - g;
				dst.at<Vec3b>(row, col)[2] = 0;

				gray_src.at<uchar>(row, col) = max(r, max(b, g));//得到r、g、b中的像素值最大值并把它转化为灰度图像
			}
		}
	}

	/*
	//方法二:使用指针访问像素
	for (int i = 0; i < gray_src.rows; i++)//行
	{
		uchar* data = gray_src.ptr<uchar>(i);//获取第i行首地址
		for (int j = 0; j < gray_src.cols; j++)//列
		{
			data[j] = 255 - data[j];
		}
	}
	//假如是三通道图像的话,j<gray_src*3
	*/

	/*
	//方法三:用迭代器操作像素
	Mat dst = src.clone();
	//获取迭代器
	Mat_<Vec3b>::iterator it = dst.begin<Vec3b>();//初始位置的迭代器
	Mat_<Vec3b>::iterator itend = dst.end<Vec3b>();//终止位置的迭代器

	//存取彩色图像像素
	for (; it != itend; ++it)
	{
		(*it)[0] = 255 - (*it)[0];
		(*it)[1] = 255 - (*it)[1];
		(*it)[2] = 0;
	}*/


	namedWindow("gray convert", CV_WINDOW_AUTOSIZE);
	imshow("gray convert", dst);
	imshow("output", gray_src);


	waitKey(0);
	return 0;
}

效果图:

                        (原图)                                                                 (单通道图)

                                                 (三通道图)

                        

二、ROI感兴趣区域的选取

        在图像处理的时候,常常我们只想对一部分图像进行处理,也就是感兴趣区域(ROI,region of interest)。我们把一部分图像区域分化独立出来进行单独处理,这样不仅减少了图像处理分析的工作量,而且有利于精度的提高和减少处理时间。

定义ROI区域的两种方法:

(1)使用Rect函数,指定矩形的左上角坐标和矩形的长宽来定义一个矩形区域作为ROI区域;

Mat imageROI = image(Rect(x, y, width, height);

(2)利用Range来指定感兴趣的行和列的范围,Range是指从初始索引到终止索引的(不包括终止索引)的一段连续序列;

Mat imageROI = image(Range(y,y+imageROI.rows),Range(x, x+image.ROI.cols));

示例程序:

//ROI感兴趣区域的选取
#include "stdafx.h"
#include<opencv2/opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;

int main(int argc, char*argv) 
{
	Mat src, dst;
	src = imread("C:/Users/59235/Desktop/image/girl1.jpg");
	if (src.empty()) 
	{
		printf("could not load image...\n");
		return -1;
	}
	imshow("original image", src);
	//cvtColor(src, src, CV_BGR2GRAY);

	// 选取 ROI区域
	//方法一:
	//dst = src(Rect(180,55,150,200));

	//方法二:
	dst = src( Range(55, 255),Range(180, 330));

	// Display Cropped Image
	imshow("Image", dst);


	waitKey(0);
	return 0;
}

效果图:

                                                           (原图)

   

  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值