欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-03-25 17:27:07
...

一、图像像素的操作

访问图像像素值是图像处理的基本操作。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;
}

效果图:

                        (原图)                                                                 (单通道图)

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

                                                 (三通道图)

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

二、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;
}

效果图:

                                                           (原图)

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