【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;
}
效果图:
(原图)
上一篇: 走进Golang之编译器原理
下一篇: LOJ#10003 加工生产调度(贪心)