图像处理之通道交换与灰度化

引言

  • 此学习是基于gitnub上一个Image Processing 100 Questions,有日语等三个版本,这是英文版,讨论的是结合opencv进行图像处理问题,有python和c++,文章以c++为主。
  • Image Processing指的是计算机等处理图像的一种技术,所以首先要知道图像在计算机中的存储方式。图像文件格式是记录和存储影像信息的格式。对数字图像进行存储、处理、传播,必须采用一定的图像格式,也就是把图像的像素按照一定的方式进行组织和存储,把图像数据存储成文件就得到图像文件。而图像以一个二维数组形式存储,要访问其像素点,可看如图(RGB图像中每个点(像素)由3个byte表示(红,绿,蓝或R,G,B三分量))

    因此一张宽度为640像素,高度为480像素分辨率的灰度图就可以表示为:
unsigned char image[480][640]

像的宽度和列数,对应着 X 轴;而图像的行数或高度,则对应着它的 Y 轴。根据这种定义方式,如果我们讨论一个位于 x, y 处的像素,那么它在程序中的访问方式应该是:

unsigned char pixel = image[y][x];

1.通道交换

将计算机中图像的 RGB 通道替换成 BGR 通道。(R:red,G:green,B:blue)
以red通道为例,

//导入opencv库
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

int main(int argc, const char* argv[]){
  cv::Mat img = cv::imread("path", cv::IMREAD_COLOR);//运用opencv读取图像,以BGR存储,path为计算机中图片的绝对路径或者相对路径

  int height = img.rows;//高为行数
  int width = img.cols;//宽为列数

  cv::Mat out = img.clone(); //复制定义一个图像

  for (int y=0; y<height; y++){
    for (int x=0; x<width; x++){
      unsigned char tmp = out.at<cv::Vec3b>(y, x)[0];//定义第三个参数,并把B通道赋值
      out.at<cv::Vec3b>(y,x)[0] = img.at<cv::Vec3b>(y,x)[2];//把R通道赋值给B通道
      out.at<cv::Vec3b>(y,x)[2] = tmp;//把B通道赋值给R通道
    }
  }

  //cv::imwrite("out.jpg", out);
  cv::imshow("sample", out);
  cv::waitKey(0);//窗口悬浮
  cv::destroyAllWindows();//释放内存空间

  return 0;

}

对于cv::Vec3b

  • vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间的目的.
  • 比如Vec<uchar, 3>:
    其实这句就是定义一个uchar类型的数组,长度为3而已,例如 8U 类型的 RGB 彩色图像可以使用 ,

    3 通道 float 类型的矩阵可以使用 。

    对于 Vec 对象,可以使用[]符号如操作数组般读写其元素,如:Vec3b color; 用 color 变量描述一种 RGB 颜色

    color[0]=255; //0通道的B 分量

    color[1]=0; //1通道的G 分量

    color[2]=0; //2通道的R 分量
  • opencv中RGB彩图通道顺序为BGR,从[0][1][2]

对于.at

  • cv::mat的成员函数: .at(int y, int x)可以用来存取图像中对应坐标为(x,y)的元素坐标。

读写像素

一个RGB像素点的像素值:

Vec3f intensity = Mat.at(y,x)

float blue = intensity.val[0] //获得蓝色通道的像素值

float green = intensity.val[1] //获得绿色通道的像素值

float red = intensity.val[2] //获得红色通道的像素值

整型:

int b = srcImage.at(row, col)[0]; //获取像素值b

int g = srcImage.at(row, col)[1]; //获取像素值g

int r = srcImage.at(row, col)[2]; //获取像素值r

2. 灰度化(Grayscale)

将图像灰度化!灰度是一种图像亮度的表示方法,通过下式计算:

Y = 0.2126 R + 0.7152 G + 0.0722 B


#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

int main(int argc, const char* argv[]){
  cv::Mat img = cv::imread("path", cv::IMREAD_COLOR)//cv::IMREAD_COLOR默认本身彩图格式读取

  int height = img.rows;
  int width = img.cols;

  cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1); //定义相同分辨率的单通道矩阵
  
  for (int y=0; y<height; y++){
    for (int x=0; x<width; x++){
      out.at<uchar>(y, x) = (int)((float)img.at<cv::Vec3b>(y,x)[0] * 0.0722 + \
				  (float)img.at<cv::Vec3b>(y,x)[1] * 0.7152 + \
				  (float)img.at<cv::Vec3b>(y,x)[2] * 0.2126);  //公式
    }
  }
  
  //cv::imwrite("out.jpg", out);
  cv::imshow("answer", out);
  cv::waitKey(0);
  cv::destroyAllWindows();//释放内存

  return 0;

}

对于 CV_8UC1

矩阵数据类型:

– CV_<bit_depth>(S|U|F)C<number_of_channels>

S = 符号整型 U = 无符号整型 F = 浮点型

CV_8UC1 是指一个8位无符号整型单通道矩阵

CV_32FC2是指一个32位浮点型双通道矩阵

CV_8UC1 CV_8SC1 CV_16U C1 CV_16SC1

CV_8UC2 CV_8SC2 CV_16UC2 CV_16SC2

CV_8UC3 CV_8SC3 CV_16UC3 CV_16SC3

CV_8UC4 CV_8SC4 CV_16UC4 CV_16SC4

CV_32SC1 CV_32FC1 CV_64FC1

CV_32SC2 CV_32FC2 CV_64FC2

CV_32SC3 CV_32FC3 CV_64FC3

CV_32SC4 CV_32FC4 CV_64FC4

其中,通道表示每个点能存放多少个数,类似于RGB彩色图中的每个像素点有三个值,即三通道的。

图片中的深度表示每个值由多少位来存储,是一个精度问题,一般图片是8bit(位)的,则深度是8.

_32FC3 CV_64FC3

CV_32SC4 CV_32FC4 CV_64FC4

其中,通道表示每个点能存放多少个数,类似于RGB彩色图中的每个像素点有三个值,即三通道的。

图片中的深度表示每个值由多少位来存储,是一个精度问题,一般图片是8bit(位)的,则深度是8.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

J先生x

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值