opencv访问图像中每个像素的值——方法总结

    1.任何图像处理算法,都是基于对每个像素的操作。

    2.任何opencv提供的图像处理库函数,只要了解算法原理,都可以写出具有相同功能的程序。

访问图像中每个像素的值:

方法一:用指针访问像素

void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{
 //参数准备
 outputImage = inputImage.clone();//复制实参到临时变量
 int rowNumber = outputImage.rows;//行数
 int colNumber = outputImage.cols*outputImage.channels();//列数*通道数=图像每行元素的个数
 
//双重循环,遍历所有像素值
for (int i = 0; i < rowNumber; i++) {
  uchar* data = outputImage.ptr<uchar>(i);//ptr函数可以获取图像第i行的首地址
  for (int j = 0; j < colNumber; j++)//列循环
  {
   //开始处理每个像素
   data[j] = data[j] / div*div + div / 2;
  }
 }
}

    备注:.clone、.rows、.cols、.channels()分别表示图像复制、读取图像行数、列数、通道数,灰度图像通道数为1,RGB图像通道数为3。opencv中的Mat类提供了ptr函数(作用:读取图像任意行的首地址),data[j]则表示第i行j列的具体像素值。

方法二:用迭代器操作像素

void colorReduce(Mat& inputImage, Mat& outputImage,int div)
{
  outputImage = inputImage.clone();//复制实参到临时变量
  //获取迭代器
  Mat_<Vec3b>::iterator it = outputImage.begin<Vec3b>();//初始位置的迭代器
  Mat_<Vec3b>::iterator itend = outputImage.end<Vec3b>();//终止位置的迭代器

  //存取彩色图像像素
  for (; it != itend; ++it) 
  {
    //处理每个像素
    (*it)[0] = (*it)[0] / div*div + div / 2;
    (*it)[1] = (*it)[1] / div*div + div / 2;
    (*it)[2] = (*it)[2] / div*div + div / 2;
  }
}

    备注:使用迭代器读取图像像素,可以防止访问越界的问题。迭代法通过获取图像矩阵的初始位置begin和终止位置end,*it表示访问当前指向的内容,++it表示从初始位置访问到终止位置。

方法三:用动态地址计算

void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{
  outputImage = inputImage.clone();//图像复制
  int rowNumber = outputImage.rows;//行数
  int colNumber = outputImage.cols;//列数

  //双重循环,处理图像每一个像素
 for (int i = 0; i < rowNumber; i++)//行循环
 {
    for (int j = 0; j < colNumber; j++)//列循环
    {
        outputImage.at<Vec3b>(i, j)[0] = outputImage.at<Vec3b>(i, j)[0] / div*div + div / 2;//[0]蓝色通道
        outputImage.at<Vec3b>(i, j)[1] = outputImage.at<Vec3b>(i, j)[1] / div*div + div / 2;//[1]绿色通道
        outputImage.at<Vec3b>(i, j)[2] = outputImage.at<Vec3b>(i, j)[2] / div*div + div / 2;//[2]红色通道
        /*outputImage.at<uchar>(i, j) = outputImage.at<uchar>(i, j)/ div*div + div / 2; */ //单通道
    }
 }
}

    备注:opencv中的Mat类提供了成员函数 at(int y, int x) 可以用来存取图像元素,但必须要知道图像的数据类型和通道数。彩色图像由三通道构成:蓝色通道、绿色通道、红色通道(BGR存储方式),每个通道8位,因而使用Vec3b。具体参考如下表格:  c1,c2,c3......表示通道数,灰度图只有1个通道(c1)。


c1c2c3c4c6
ucharucharVec2bVec3b
Vec4b

shortshortVec2s
Vec3s
Vec4s

int intVec2i
Vec3i
Vec4i

floatfloatVec2f
Vec3f
Vec4f
Vec6f
doubledoubleVec2d
Vec3d
Vec4d
Vec6d

  附录:数据类型及其取值范围

数值具体类型取值范围
CV_8U
8 位无符号整数
(0…..255)
CV_8S
8 位符号整数
(-128…..127)
CV_16U
16 位无符号整数
(0……65535)
CV_16S
16 位符号整数
(-32768…..32767)
CV_32S
32 位符号整数
(-2147483648……2147483647)
CV_32F
32 位浮点数
(-FLT_MAX ………FLT_MAX,INF,NAN)
CV_64F
64 位浮点数
(-DBL_MAX ……….DBL_MAX,INF,NAN)



  • 6
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Opencv的分水岭算法(watershed algorithm)是一种自动图像分割算法,常用于分离图像的前景和背景。下面是使用Opencv的分水岭算法进行图像分割的步骤: 1. 读入图像并进行预处理,如去噪、灰度化等。 2. 对图像进行二化处理,得到前景和背景的二图像。 3. 对二图像进行距离变换(distance transform),得到每个像素离最近的背景像素的距离。 4. 对距离变换后的图像进行阈处理,得到图像的分水岭标记(watershed markers)。 5. 对分水岭标记进行修正,确保标记不会重叠或出现空洞。 6. 对分水岭标记应用分水岭算法,得到分割后的图像。 下面是使用Opencv实现分水岭算法的示例代码: ```python import cv2 import numpy as np # 读取图像并进行预处理 img = cv2.imread('input.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) # 进行距离变换 dist_transform = cv2.distanceTransform(thresh,cv2.DIST_L2,5) ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0) # 获取分水岭标记 sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(thresh,sure_fg) ret, markers = cv2.connectedComponents(sure_fg) markers = markers+1 markers[unknown==255] = 0 # 修正分水岭标记 markers = cv2.watershed(img,markers) img[markers == -1] = [255,0,0] # 显示分割结果 cv2.imshow('result', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 这段代码,我们首先读入一张图像并进行预处理,然后进行距离变换,得到每个像素到最近的背景像素的距离。接着使用阈处理得到分水岭标记,修正分水岭标记并应用分水岭算法,最后显示分割结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值