我是靠谱客的博主 震动白云,最近开发中收集的这篇文章主要介绍opencv学习笔记(五)-- 图像操作读写图像读写像素感兴趣区域(ROI)的选择与提取完整代码(详细注释),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

  • 读写图像
  • 读写像素
    • 灰度图像像素点值的获取
    • RGB图像像素点值获取
    • 修改像素点值
    • 应用实例之图像反转
      • 反转部分实现代码
      • bitwise_not()函数实现图像反转
    • 对空白图像赋值【Scalar()函数】
  • 感兴趣区域(ROI)的选择与提取
  • 完整代码(详细注释)

读写图像

之前已经介绍过的两个函数:
imread 可以指定加载为灰度或者RGB图像
imwrite保存图像文件,类型由扩展名决定
具体介绍可以参考我的另一篇文章:
https://blog.csdn.net/milkhoko/article/details/111997017

读写像素

灰度图像像素点值的获取

Scalar intensity_gray = gray_src.at<uchar>(120,200);

或者

Scalar intensity_gray = gray_src.at<uchar>(Point(200,120));

注意这里小括号中x,y的顺序,当使用Point()时是先x后y,不使用时是先y后x,即先行数再列数。
说明:
图像左上角为坐标原点,向右为x轴正向,向下为y轴正向

Scalar intensity = img.at(y, x);

Scalar intensity = img.at(Point(x, y));

RGB图像像素点值获取

	Vec3b intensity_src = src.at<Vec3b>(120, 200);
	float blue = intensity_src.val[0];
	float green = intensity_src.val[1];
	float red = intensity_src.val[2];

我们将这些值输出可以得到下面的结果
在这里插入图片描述

修改像素点值

我们同样可以使用上面的获取像素点值的方式来修改对应的像素点值

	gray_src.at<uchar>(y, x) = 50;

当我们运行如下代码:

	for (int x=50;x<80;x++)
		for(int y=50;y<80;y++)
		{
			gray_src.at<uchar>(y, x) = 50;
		}
	imshow("output",gray_src);

我们可以看到在对应图像的对应区域的像素值被改变(图中黑框):
在这里插入图片描述

应用实例之图像反转

反转部分实现代码

完整代码见文章末尾—建议使用完整代码进行学习

	Mat dst;	//定义新的 Mat对象dst
	dst.create(src.size(), src.type());	//create一个大小类型和src图像一致的对象[对谁(src或gray_src)反转就创建和其大小和类型相同的空白图像]
	for (int row = 0; row < height; row++) {	//行扫描
		for (int col = 0; col < width; col++) {		//列扫描
			if (dst.channels() == 1) {	//当src图像为单通道(灰度图)时
				int gray = gray_src.at<uchar>(row, col);
				dst.at<uchar>(row, col) = 255 - gray;
			}
			else if (dst.channels() == 3) {	当src图像为三通道(BGR图)时
				int b = src.at<Vec3b>(row, col)[0];		//获取B通道某点像素值
				int g = src.at<Vec3b>(row, col)[1];		//获取B通道某点像素值
				int r = src.at<Vec3b>(row, col)[2];		//获取B通道某点像素值
				dst.at<Vec3b>(row, col)[0] = 255 - b;	//对图像B通道某点像素值进行反转
				dst.at<Vec3b>(row, col)[1] = 255 - g;	//对图像G通道某点像素值进行反转
				dst.at<Vec3b>(row, col)[2] = 255 - r;	//对图像R通道某点像素值进行反转
			}
		}
	}
	imshow("output", dst);	//显示反转之后的图像
	waitKey(0);	//等待按键后结束程序

这里对dst图像(BGR三通道)进行反转,运行结果为:
在这里插入图片描述
修改程序中的

dst.create(src.size(), src.type());	

dst.create(gray_src.size(), gray_src.type());

可以对灰度图像进行反转,反转后结果为:

在这里插入图片描述

bitwise_not()函数实现图像反转

	//上面的例子(求反转图片)可以用下面的函数来代替
	bitwise_not(gray_src, dst);	//对像素值进行反转操作
	imshow("output", dst);	//显示反转后的图像

小括号中第一个元素为反转前的图像,第二个元素为反转之后的图像
运行结果和上面一样:
在这里插入图片描述

对空白图像赋值【Scalar()函数】

	//空白图像的赋值
	Mat image0;
	image0.create(src.size(), src.type());
	image0 = Scalar(0, 0, 250);
	imshow("output",image0);

首先创建一个空白Mat对象,并且使用create使其大小和类型和src图像一致(或其他大小和类型,同理)
接着使用Scalar()对其赋值,由于src为三通道图像,所以小括号中填三个值,分别对应通道B、G、R。
这里运行输出结果为:
在这里插入图片描述

感兴趣区域(ROI)的选择与提取

	//ROI(感兴趣区域)的提取
	Rect r(50,50, 150, 150);
	Mat smallImg = src(r);
	imshow("output",smallImg);

这里的Rect创建一个区域范围(x, y, x_width, y_height),前两个参数表示的时矩形区域开始的坐标,后两个参数分别表示x和y增加的坐标,即
Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);
在这里插入图片描述
运行结果为
在这里插入图片描述
右图为提取出来的ROI,范围为(50,50)到(200,200)

完整代码(详细注释)

每一部分结束都会加一个waitKey(0);
程序运行时,按下任意按键即可继续运行下一部分代码

#include<opencv2/opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;

int main(int argc, char** argv) {
	Mat src, gray_src;	//创建Mat对象src保存bge格式的原图,gray_src保存cvtcolor后的gray灰度图
	src = imread("A:/opencvproject/pikaqiu.jpg",IMREAD_COLOR);	//读bgr格式的原图保存在src中
	if (src.empty()){	//确保图像存在,并正确读入
		cout << "could not load image..." << endl;
		return -1;
	}
	namedWindow("input", CV_WINDOW_AUTOSIZE);	//创建输入图像窗口
	imshow("input", src);	//显示BGR格式的输入图像

	cvtColor(src,gray_src,CV_BGR2GRAY);	//格式转换BGR-->GRAY
	int height = gray_src.rows;	//获取灰度图的行数(和BGR格式的行数一致)
	int width = gray_src.cols;	//获取灰度图的列数(和BGR格式的列数一致)
	namedWindow("output",CV_WINDOW_AUTOSIZE);	//创建输出窗口
	imshow("output", gray_src);	//显示灰度图输出
	cout << "rows is:" << height << "n" << "cols is:" << width << endl;	//打印灰度图的长宽
	waitKey(0);	//等待按键,按键之后开始下一步

	//单通道像素值获取
	Scalar intensity_gray = gray_src.at<uchar>(120,200);	//获取灰度图的第 120 行,第 200 列的像素值
	cout << "gray_src vaul of (120,200) =" << intensity_gray << endl;	//打印获取到的像素值
	
	//三通道(BGR)像素值获取
	Vec3b intensity_src = src.at<Vec3b>(120, 200);	//获取BGR图像的第 120 行,第 200 列的像素值
	cout << "src vaul of (120,200) =" << intensity_src << endl;	//打印获取到的像素值
	int blue = intensity_src[0];		//分别获取像素值的B、G、R通道对应的值
	int green = intensity_src[1];
	int red = intensity_src[2];
	cout << "blue vaul is:" << blue << endl;	//分别打印对应通道的值
	cout << "green vaul is:" << green << endl;
	cout << "red vaul is:" << red << endl;
	waitKey(0);	//等待按键开始下一步

	for (int x = 50; x < 80; x++)	//上面获取到了对应像素点的值,下面开始用同样的方式修改像素点的值
		for (int y = 50; y < 80; y++)
		{
			gray_src.at<uchar>(y, x) = 50;	//修改GRAY灰度图50-80行和列围成的30*30的正方形的像素值为50
		}
	imshow("output", gray_src);	//在output窗口显示修改后的图像
	waitKey(0);	//等待按键,按键后进行下一步

	//下面用反转图像的例子来应用像素值的获取和修改
	Mat dst;	//定义新Mat对象dst
	dst.create(gray_src.size(), gray_src.type());	//create一个大小类型和src图像一致的对象[对谁(src或gray_src)反转就创建和其大小和类型相同的空白图像]
	for (int row = 0; row < height; row++) {	//行扫描
		for (int col = 0; col < width; col++) {		//列扫描
			if (dst.channels() == 1) {	//当src图像为单通道(灰度图)时
				int gray = gray_src.at<uchar>(row, col);
				dst.at<uchar>(row, col) = 255 - gray;
			}
			else if (dst.channels() == 3) {	当src图像为三通道(BGR图)时
				int b = src.at<Vec3b>(row, col)[0];		//获取B通道某点像素值
				int g = src.at<Vec3b>(row, col)[1];		//获取B通道某点像素值
				int r = src.at<Vec3b>(row, col)[2];		//获取B通道某点像素值
				dst.at<Vec3b>(row, col)[0] = 255 - b;	//对图像B通道某点像素值进行反转
				dst.at<Vec3b>(row, col)[1] = 255 - g;	//对图像G通道某点像素值进行反转
				dst.at<Vec3b>(row, col)[2] = 255 - r;	//对图像R通道某点像素值进行反转
			}
		}
	}
	imshow("output", dst);	//显示反转之后的图像
	waitKey(0);	//等待按键后结束程序

	//上面的例子(求反转图片)可以用下面的函数来代替
	bitwise_not(gray_src, dst);	//对像素值进行反转操作
	imshow("output", dst);	//显示反转后的图像
	waitKey(0);

	//空白图像的赋值
	Mat image0;	//创建一个新的Mat对象image0
	image0.create(src.size(), src.type());	//其大小和类型与src一致
	image0 = Scalar(0, 0, 250);	//使用Scalar()对BGR三通道图像赋值
	imshow("output",image0);	//输出显示得到的图像
	waitKey(0);

	//ROI(感兴趣区域)的提取
	Rect r(50,50, 150, 150);	//选择一个矩形区域(50,50)-->(200,200)
	Mat smallImg = src(r);		//在src图像上提取对应区域
	imshow("output",smallImg);	//显示对应区域
	waitKey(0);
	return 0;
}

最后

以上就是震动白云为你收集整理的opencv学习笔记(五)-- 图像操作读写图像读写像素感兴趣区域(ROI)的选择与提取完整代码(详细注释)的全部内容,希望文章能够帮你解决opencv学习笔记(五)-- 图像操作读写图像读写像素感兴趣区域(ROI)的选择与提取完整代码(详细注释)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部