• 4--OpenCV:图像像素的读写&像素运算


    opencv图像像素读写操作

    常用类型介绍

    • uchar类型

    typedef unsigned uint;
    typedef signed char schar;
    typedef unsigned char uchar;
    typedef unsigned short ushort;
    • Vec系列

      Vec+数字+字母: C++STL vector容器类似

      • 数字: Vec 的长度

      • 字母: 类型

        • b: uchar

        • s:short

        • w: ushort

        • i: int

        • f:float

        • d:double

    typedef Vec Vec2b;
    typedef Vec Vec3b;
    typedef Vec Vec4b;
    ​
    typedef Vec Vec2s;
    typedef Vec Vec3s;
    typedef Vec Vec4s;
    ​
    typedef Vec Vec2w;
    typedef Vec Vec3w;
    typedef Vec Vec4w;
    ​
    typedef Vec Vec2i;
    typedef Vec Vec3i;
    typedef Vec Vec4i;
    typedef Vec Vec6i;
    typedef Vec Vec8i;
    ​
    typedef Vec Vec2f;
    typedef Vec Vec3f;
    typedef Vec Vec4f;
    typedef Vec Vec6f;
    ​
    typedef Vec Vec2d;
    typedef Vec Vec3d;
    typedef Vec Vec4d;
    typedef Vec Vec6d;

    图像的像素读写

    数组方式读写

    注意:①at方法的使用,是Mat中的模板函数,需要实例化,(unsigned char---->8个位都是用来存储相关的像素信息),然后传入x,y坐标即可。

            其返回值是引用类型,所以才有了下面的负片处理

              ②Mat中channels()方法获取图片的通道数,是一维的(黑白)还是三维的(rgb)

              ③注意dims=3的情况,如何接收pixel值的?--->Vec3b类型的容器接收。

    1. int dims = img.channels(); //得到图片通道数
    2. for (int i = 0; i < img.rows; i++)
    3. {
    4. for (int j = 0; j < img.cols; j++)
    5. {
    6. if (dims == 1)
    7. {
    8. //单通道图像像素点获取
    9. int pixel = img.at(i, j);
    10. img.at(i, j) = 255 - pixel; //负片处理
    11. }
    12. if (dims == 3)
    13. {
    14. //三通道图像像素点获取
    15. Vec3b bgr = img.at(i, j);
    16. //负片处理
    17. img.at(i, j)[0] = 255 - bgr[0];
    18. img.at(i, j)[1] = 255 - bgr[1];
    19. img.at(i, j)[2] = 255 - bgr[2];
    20. }
    21. }
    22. }

    指针方式读写

    注意:Mat中的成员函数ptr用uchar实例化之后,传入要获取的行数,即可。

    1. //二维数组-->一级指针访问二维数组方式
    2. int dims = img.channels();
    3. for (int i = 0; i < img.rows; i++)
    4. {
    5. //Mat中有一个ptr成员函数,获取当前i行的指针
    6. uchar* current_row = img.ptr(i);
    7. for (int j = 0; j < img.cols; j++)
    8. {
    9. if (dims == 1)
    10. {
    11. int pixel = *current_row;   //current_row[j];
    12. *current_row++ = 255 - pixel;  //做一个横向移动
    13. }
    14. if (dims == 3)
    15. {
    16. Vec3b bgr = img.at(i, j);
    17. *current_row++ = 255 - *current_row;
    18. *current_row++ = 255 - *current_row;
    19. *current_row++ = 255 - *current_row;
    20. }
    21. }
    22. }

            注意:*p++中*和++的运算优先级相同,自右向左的运算顺序,

                                    所以先++(指针的指向先发生改变) 

    完整案例

    1. #include
    2. #include
    3. using namespace cv;
    4. using namespace std;
    5. class ImgVisitPixel
    6. {
    7. public:
    8. ImgVisitPixel(int type = IMREAD_UNCHANGED) :img(imread("mm.jpg",type)) {}
    9. void Show(string wName)
    10. {
    11. imshow(wName, img);
    12. moveWindow(wName, 600, 300);
    13. waitKey(0);
    14. }
    15. void Visit_By_Array();
    16. void Visit_By_Point();
    17. protected:
    18. Mat img;
    19. };
    20. void ImgVisitPixel::Visit_By_Array()
    21. {
    22. int dims = img.channels(); //得到图片通道数
    23. for (int i = 0; i < img.rows; i++)
    24. {
    25. for (int j = 0; j < img.cols; j++)
    26. {
    27. if (dims == 1)
    28. {
    29. //单通道图像像素点获取
    30. int pixel = img.at(i, j);
    31. img.at(i, j) = 255 - pixel; //负片处理
    32. }
    33. if (dims == 3)
    34. {
    35. //三通道图像像素点获取
    36. Vec3b bgr = img.at(i, j);
    37. //负片处理
    38. img.at(i, j)[0] = 255 - bgr[0];
    39. img.at(i, j)[1] = 255 - bgr[1];
    40. img.at(i, j)[2] = 255 - bgr[2];
    41. }
    42. }
    43. }
    44. }
    45. void ImgVisitPixel::Visit_By_Point()
    46. {
    47. int dims = img.channels();
    48. for (int i = 0; i < img.rows; i++)
    49. {
    50. //Mat中有一个ptr成员函数,获取当前i行的指针
    51. uchar* current_row = img.ptr(i);
    52. for (int j = 0; j < img.cols; j++)
    53. {
    54. if (dims == 1)
    55. {
    56. int pixel = *current_row;   //current_row[j];
    57. *current_row++ = 255 - pixel;  //做一个横向移动
    58. }
    59. if (dims == 3)
    60. {
    61. Vec3b bgr = img.at(i, j);
    62. *current_row++ = 255 - *current_row;
    63. *current_row++ = 255 - *current_row;
    64. *current_row++ = 255 - *current_row;
    65. }
    66. }
    67. }
    68. }
    69. int main()
    70. {
    71. ImgVisitPixel* pImg = new ImgVisitPixel;
    72. pImg->Show("原图");
    73. pImg->Visit_By_Array();
    74. pImg->Show("第一次负片操作");
    75. pImg->Visit_By_Point();
    76. pImg->Show("第二次负片操作");
    77. return 0;
    78. }

    像素读写注意点

    在读取到像素点的时候,做一些算数运算,一定要注意颜色范围问题小心溢出,针对溢出,opencv提供一个转换防止溢出

    saturate_cast<要转换的类型>(要转换的数据)

    • 小于0 等于0

    • 大于255 直接等于255

    1. img.at(i, j)[0] =saturate_cast(bgr[0]+100);
    2. img.at(i, j)[1] = saturate_cast(bgr[1] + 100);
    3. img.at(i, j)[2] = saturate_cast(bgr[2] + 100);

    opencv图像像素运算

    注意:参与算术运算图像的数据类型、通道数目、大小必须相同!!!

    算术运算

    加法:add

    1. void add(InputArray src1, InputArray src2, OutputArray dst,InputArray mask = noArray(), int dtype = -1);
    2. /*******************************************************************
    3. * src1: 输入图1
    4. * src2: 输入图2
    5. * dst: 输出图
    6. * mask: 遮罩像素 可有可无
    7. * dtype: 输出图深度 可有可无
    8. *********************************************************************/

    减法:subtract

    1. void subtract(InputArray src1,InputArray src2,OutputArray dst,InputArray mask = noArray(),int dtype = -1);
    2. /*******************************************************************
    3. * src1: 输入图1
    4. * src2: 输入图2
    5. * dst: 输出图
    6. * mask: 遮罩像素 可有可无
    7. * dtype: 输出图深度 可有可无
    8. *********************************************************************/

    乘法:multiply

    1. void multiply(InputArray src1, InputArray src2,OutputArray dst, double scale = 1, int dtype = -1);
    2. /*******************************************************************
    3. * src1: 输入图1
    4. * src2: 输入图2
    5. * dst: 输出图
    6. * scale: 缩放因子,即在src1*src2的基础上再乘scale
    7. * dtype: 输出图深度 可有可无
    8. *********************************************************************/

    除法:divide

    1. void divide(InputArray src1, InputArray src2, OutputArray dst,double scale = 1, int dtype = -1);
    2. /*******************************************************************
    3. * src1: 输入图1
    4. * src2: 输入图2
    5. * dst: 输出图
    6. * scale: 缩放因子,即在src1*src2的基础上再乘scale
    7. * dtype: 输出图深度 可有可无
    8. *********************************************************************/

    混合运算:addWeighted

    dst = α · img1 + β · img2 + γ

    1. void addWeighted(InputArray s1,double a,InputArray s2,double b,double gamma,OutputArray d,int dtype = -1);
    2. /*******************************************************************
    3. * s1: 输入图1
    4. * a: 输入图占比 α
    5. * s2: 输入图2
    6. * b:     输入图2占比 β
    7. * gamma: 附加值,结果基础上再加+gamma   γ  
    8. * dst: 输出图
    9. * dtype: 输出图深度 可有可无
    10. *********************************************************************/

    综合代码

    1. #include
    2. #include
    3. using namespace cv;
    4. using namespace std;
    5. class ImgOpreations
    6. {
    7. public:
    8. ImgOpreations() :img1(imread("mm.jpg")), img2(imread("text.jpg"))
    9. {
    10. result = Mat::zeros(img1.size(), img2.type()); //存储的图像一定要初始化
    11. }
    12. void testAdd(string wName="Add")
    13. {
    14. add(img1, img2, result);
    15. imshow(wName, result);
    16. waitKey(0);
    17. }
    18. void testSub(string wName="Sub")
    19. {
    20. subtract(img1, img2, result);
    21. imshow(wName, result);
    22. waitKey(0);
    23. }
    24. void testMul(string wName="Mul")
    25. {
    26. multiply(img1, img2, result);
    27. imshow(wName, result);
    28. waitKey(0);
    29. }
    30. void testDivide(string wName = "Div")
    31. {
    32. divide(img1, img2, result);
    33. imshow(wName, result);
    34. waitKey(0);
    35. }
    36. //dst = α · img1 + β · img2 + γ  
    37. void testAddWeighted(string wName = "AddWeighted")
    38. {
    39. addWeighted(img1, 0.6, img2, 0.4, 0, result);
    40. imshow(wName, result);
    41. waitKey(0);
    42. }
    43. protected:
    44. Mat img1;
    45. Mat img2;
    46. Mat result;
    47. };
    48. int main()
    49. {
    50. ImgOpreations* pImg = new ImgOpreations;
    51. pImg->testAdd();
    52. pImg->testSub();
    53. pImg->testMul();
    54. pImg->testDivide();
    55. pImg->testAddWeighted();
    56. return 0;
    57. }

    位运算 

    位与

    1. void bitwise_and(InputArray src1, InputArray src2,,OutputArray dst, InputArray mask = noArray());
    2. /*******************************************************************
    3. * src1: 输入图1
    4. * src2: 输入图2
    5. * dst: 输出图
    6. * mask: 遮罩像素 可有可无
    7. *********************************************************************/

    位或

    1. void bitwise_or(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray());
    2. /*******************************************************************
    3. * src1: 输入图1
    4. * src2: 输入图2
    5. * dst: 输出图
    6. * mask: 遮罩像素 可有可无
    7. *********************************************************************/

    非运算

    1. void bitwise_not(InputArray src, OutputArray dst,InputArray mask = noArray());
    2. /*******************************************************************
    3. * src1: 输入图1
    4. * dst: 输出图
    5. * mask: 遮罩像素 可有可无
    6. *********************************************************************/

    异或运算

    1. void bitwise_xor(InputArray src1, InputArray src2,OutputArray dst, InputArray mask = noArray());
    2. /*******************************************************************
    3. * src1: 输入图1
    4. * src2: 输入图2
    5. * dst: 输出图
    6. * mask: 遮罩像素 可有可无
    7. *********************************************************************/

    综合代码:图像位运算用图片

    1. #include
    2. #include
    3. using namespace cv;
    4. using namespace std;
    5. class BitWise
    6. {
    7. public:
    8. BitWise() :img1(imread("mm.jpg")), img2(imread("text.jpg")) {}
    9. void Show()
    10. {
    11. imshow("mm", img1);
    12. imshow("text", img2);
    13. }
    14. void BitOpreations()
    15. {
    16. Mat myand, myor, myxor, mynot;
    17. bitwise_and(img1, img2, myand);
    18. bitwise_or(img1, img2, myor);
    19. bitwise_not(img1, mynot);
    20. bitwise_xor(img1, img2, myxor);
    21. imshow("and", myand);
    22. imshow("or", myor);
    23. imshow("xor", myxor);
    24. imshow("not", mynot);
    25. waitKey(0);
    26. }
    27. protected:
    28. Mat img1;
    29. Mat img2;
    30. };
    31. int main()
    32. {
    33. BitWise* pImg = new BitWise;
    34. pImg->Show();
    35. pImg->BitOpreations();
    36. return 0;
    37. }

    图像位运算用自绘图图形

    注意:       

            ①函数Scalar的使用,传入一个参数就是单通道,三个参数就是RGB

            ②注意构造函数的写法,在Mat类型的img中利用Rect函数进行绘制。

    1. #include
    2. #include
    3. using namespace cv;
    4. using namespace std;
    5. class BitWise
    6. {
    7. public:
    8. BitWise() :img1(Mat(200,200,CV_8UC1)), img2(Mat(200,200,CV_8UC1))
    9. {
    10. //Rect绘制矩形(左上角坐标 和绘制矩形宽度和高度)
    11. img1(Rect(50, 50, 100, 100)) = Scalar(255);
    12. img2(Rect(100, 100, 100, 100)) = Scalar(255);
    13. }
    14. void Show()
    15. {
    16. imshow("mm", img1);
    17. imshow("text", img2);
    18. waitKey(0);
    19. }
    20. void BitOpreations()
    21. {
    22. Mat myand, myor, myxor, mynot;
    23. bitwise_and(img1, img2, myand);
    24. bitwise_or(img1, img2, myor);
    25. bitwise_not(img1, mynot);
    26. bitwise_xor(img1, img2, myxor);
    27. imshow("and", myand);
    28. imshow("or", myor);
    29. imshow("xor", myxor);
    30. imshow("not", mynot);
    31. waitKey(0);
    32. }
    33. protected:
    34. Mat img1;
    35. Mat img2;
    36. };
    37. int main()
    38. {
    39. BitWise* pImg = new BitWise;
    40. pImg->Show();
    41. pImg->BitOpreations();
    42. return 0;
    43. }

  • 相关阅读:
    Linux python2升级到python3
    LLM ReAct: 将推理和行为相结合的通用范式 学习记录
    2023-9-8 求组合数(二)
    学习JavaScript基础
    青少年软件编程C++二级真题(202109)
    敏感词检测库ToolGood.Words中 WordsHelper类使用简介
    Litetouch deployment failed, Return Code = -2147024894 0x80070002
    MobTech ShareSDK Android端快速集成
    优思学院|精益六西格玛中的8大浪费是什么?
    websocket通信案例
  • 原文地址:https://blog.csdn.net/zjjaibc/article/details/126463078