<LearnOpenCV(4) C++>图像的像素操作

发布于:2022-12-02 ⋅ 阅读:(197) ⋅ 点赞:(0)

像素操作

本文了解单通道图像与三通道图像的像素操作,包括指针访问和非指针访问。

指针访问

单通道指针访问

定义一个uchar指针指向第row行元素,将第row行元素视为数组,按索引访问。

height = gray_src2.rows;
width = gray_src2.cols;
for (int row = 0; row < height; row++)
{
    uchar* current = gray_src2.ptr<uchar>(row);
    for (int col = 0; col < width; col++)
    {
        int gray = current[col];
        current[col] = saturate_cast < uchar>(255 - gray);
    }
}

三通道指针访问

三通道指针访问需要注意的是当uchar指针指向row行时,row行的数组长度应该是cols x channels 即列数 × 通道数(看<LearnOpenCV(2)>)。这里的访问也是按索引访问,只不过是内循环的范围定义不同。

height = color_src2.rows;
width = color_src2.cols*color_src2.channels();//内循环范围定义不同
for (int row = 0; row < height; row++)
{
    uchar* current = color_src2.ptr<uchar>(row);
    for (int col = 0; col < width; col++)
    {
        current[col] = 255 - current[col];
    }
}

非指针

使用Mat.at<type>(row,col)访问。

单通道非指针访问

int height = gray_src1.rows;
int width = gray_src2.cols;
for (int row = 0; row < height; row++)
{
    for (int col = 0; col < width; col++)
    {
        int gray = gray_src1.at<uchar>(row, col);
        gray_src1.at<uchar>(row, col) = 255 - gray;//单通道的数据类型是uchar
    }
}

三通道非指针访问

height = color_src1.rows;
	width = color_src1.cols;

	for (int row = 0; row < height; row++)
	{
		for (int col = 0; col < width; col++)
		{
			int b = color_src1.at<Vec3b>(row, col)[0];//Vec3b对应的是bgr的uchar类型 还有Vec3f 是对应float类型
			int g = color_src1.at<Vec3b>(row, col)[1];//可以看出3通道的访问中,非指针是要简洁一些,另外指针访问也不怎么安全
			int r = color_src1.at<Vec3b>(row, col)[2];
			color_src1.at<Vec3b>(row, col)[0] = 255 - b;
			color_src1.at<Vec3b>(row, col)[1] = 255 - g;
			color_src1.at<Vec3b>(row, col)[2] = 255 - r;
		}
	}

另外的函数

这个与上面的取反操作相同

// 取反函数 bitwise_not
	Mat bitwise = src.clone();
	bitwise_not(src, bitwise);

代码

//通过单通道与三通道的图像反转了解图像像素的取值与赋值,
#include<opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main() {
	Mat src, gray_src1,gray_src2,color_src1,color_src2;
	 src = imread("girl4.jpg");
	 // 单通道像素操作 //
	cvtColor(src, gray_src1, COLOR_BGR2GRAY);
	gray_src2 = gray_src1.clone();
	//单通道非指针访问
	int height = gray_src1.rows;
	int width = gray_src2.cols;
	for (int row = 0; row < height; row++)
	{
		for (int col = 0; col < width; col++)
		{
			int gray = gray_src1.at<uchar>(row, col);
			gray_src1.at<uchar>(row, col) = 255 - gray;
		}
	}
	//单通道指针访问
	height = gray_src2.rows;
	width = gray_src2.cols;
	for (int row = 0; row < height; row++)
	{
		uchar* current = gray_src2.ptr<uchar>(row);
		for (int col = 0; col < width; col++)
		{
			int gray = current[col];
			current[col] = saturate_cast < uchar>(255 - gray);
		}
	}
	//三通道像素操作//
	color_src1 = src.clone();
	color_src2 = src.clone();
	//三通道非指针访问
	height = color_src1.rows;
	width = color_src1.cols;
	for (int row = 0; row < height; row++)
	{
		for (int col = 0; col < width; col++)
		{
			int b = color_src1.at<Vec3b>(row, col)[0];//Vec3b对应的是bgr的uchar类型 还有Vec3f 是对应float类型
			int g = color_src1.at<Vec3b>(row, col)[1];
			int r = color_src1.at<Vec3b>(row, col)[2];
			color_src1.at<Vec3b>(row, col)[0] = 255 - b;
			color_src1.at<Vec3b>(row, col)[1] = 255 - g;
			color_src1.at<Vec3b>(row, col)[2] = 255 - r;
		}
	}
	//三通道指针访问
	height = color_src2.rows;
	width = color_src2.cols*color_src2.channels();//内循环范围定义不同
	for (int row = 0; row < height; row++)
	{
		uchar* current = color_src2.ptr<uchar>(row);
		for (int col = 0; col < width; col++)
		{
			current[col] = 255 - current[col];
		}
	}
	gray_src1, gray_src2, color_src1, color_src2;
	imshow("src", src);
	imshow("gray_src1", gray_src1);
	imshow("gray_src2", gray_src2);
	imshow("color_src1", color_src1);
	imshow("color_src2", color_src2);
	// 取反函数 bitwise_not//
	Mat bitwise = src.clone();
	bitwise_not(src, bitwise);
	imshow("bitwise", bitwise);
	waitKey(0);
	return 0;
}

在这里插入图片描述
在这里插入图片描述

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到