16.两图像间的像素操作
1、两张图像的比较运算
OpenCV 4中提供了求取两张图像每一位像素较大或者较小灰度值的max()、min()函数,这两个函数分别比较两个图像中每一位元素灰度值的大小,保留较大(较小)的灰度值,这两个函数的函数原型在代码清单3-13中给出。
代码清单3-13 max()和min()函数原型 1. void cv::max(InputArray src1, 2. InputArray src2, 3. OutputArray dst 4. ) 5. void cv::min(InputArray src1, 6. InputArray src2, 7. OutputArray dst 8. )
-
src1:第一个图像矩阵,可以是任意通道数的矩阵。
-
src2:第二个图像矩阵,尺寸和通道数以及数据类型都需要与src1一致。
-
dst:保留对应位置较大(较小)灰度值后的图像矩阵,尺寸、通道数和数据类型与src1一致。
该函数的功能相对来说比较简单,就是比较图像每个像素的大小,按要求保留较大值或者较小值,最后生成新的图像。例如,第一张图像位置像素值为100,第二张图像
位置像素值为10,那么输出图像
位置像素值为100。在代码清单3-14中给出了这两个函数的代码实现过程以及运算结果,运算结果在图3-9、图3-10和图3-11中给出。这种比较运算主要用在对矩阵类型数据的处理,与掩模图像进行比较运算可以实现抠图或者选择通道的效果。
代码清单3-14 myMaxAndMin.cpp两个矩阵或图像进行比较运算 1. #include <opencv2\opencv.hpp> 2. #include <iostream> 3. #include <vector> 4. 5. using namespace std; 6. using namespace cv; 7. 8. int main() 9. { 10. float a[12] = { 1, 2, 3.3, 4, 5, 9, 5, 7, 8.2, 9, 10, 2 }; 11. float b[12] = { 1, 2.2, 3, 1, 3, 10, 6, 7, 8, 9.3, 10, 1 }; 12. Mat imga = Mat(3, 4, CV_32FC1, a); 13. Mat imgb = Mat(3, 4, CV_32FC1, b); 14. Mat imgas = Mat(2, 3, CV_32FC2, a); 15. Mat imgbs = Mat(2, 3, CV_32FC2, b); 16. 17. //对两个单通道矩阵进行比较运算 18. Mat myMax, myMin; 19. max(imga, imgb, myMax); 20. min(imga, imgb, myMin); 21. 22. //对两个多通道矩阵进行比较运算 23. Mat myMaxs, myMins; 24. max(imgas, imgbs, myMaxs); 25. min(imgas, imgbs, myMins); 26. 27. //对两张彩色图像进行比较运算 28. Mat img0 = imread("lena.png"); 29. Mat img1 = imread("noobcv.jpg"); 30. if (img0.empty()|| img1.empty()) 31. { 32. cout << "请确认图像文件名称是否正确" << endl; 33. return -1; 34. } 35. Mat comMin, comMax; 36. max(img0, img1, comMax); 37. min(img0, img1, comMin); 38. imshow("comMin", comMin); 39. imshow("comMax", comMax); 40. 41. //与掩模进行比较运算 42. Mat src1 = Mat::zeros(Size(512, 512), CV_8UC3); 43. Rect rect(100, 100, 300, 300); 44. src1(rect) = Scalar(255, 255, 255); //生成一个低通300*300的掩模 45. Mat comsrc1, comsrc2; 46. min(img0, src1, comsrc1); 47. imshow("comsrc1", comsrc1); 48. 49. Mat src2 = Mat(512, 512, CV_8UC3, Scalar(0,0, 255)); //生成一个显示红色通道的低通掩模 50. min(img0, src2, comsrc2); 51. imshow("comsrc2", comsrc2); 52. 53. //对两张灰度图像进行比较运算 54. Mat img0G, img1G, comMinG, comMaxG; 55. cvtColor(img0, img0G, COLOR_BGR2GRAY); 56. cvtColor(img1, img1G, COLOR_BGR2GRAY); 57. max(img0G, img1G, comMaxG); 58. min(img0G, img1G, comMinG); 59. imshow("comMinG", comMinG); 60. imshow("comMaxG", comMaxG); 61. waitKey(0); 62. return 0; 63. }
2、两张图像的逻辑运算
OpenCV 4针对两个图像像素之间的与、或、异或以及非运算提供了bitwise_and()、bitwise_or()、bitwise_xor()和bitwise_not()四个函数,在代码清单3-15中给出了这四个函数的函数原型。在了解函数用法之前,我们先了解一下图像像素逻辑运算的规则。图像像素间的逻辑运算与数字间的逻辑运算相同,具体规则在图3-12中给出。像素的非运算只能针对一个数值进行,因此在图3-12中对像素求非运算时对图像1的像素值进行非运算。如果像素取值只有0和1的话,那么图中的前4行数据正好对应了所有的运算规则,但是CV_8U类型的图像像素值从0取到255,此时的逻辑运算就需要将像素值转成二进制数后再进行,因为CV_8U类型是8位数据,因此对0求非是11111111,也就是255。在图3-12中最后一行数据中,像素值5对应的二进制为101,像素值6对应的二进制是110,因此与运算得100(4),或运算得111(7),异或运算得011(3),对像素值5进行非运算得11111010(250)。了解了像素的辑运算原理之后,我们再来看OpenCV 4中提供的辑运算函数的使用方法。
代码清单3-15 OpenCV 4中像素逻辑运算函数原型 1. //像素求与运算 2. void cv::bitwise_and(InputArray src1, 3. InputArray src2, 4. OutputArray dst, 5. InputArray mask = noArray() 6. ) 7. //像素求或运算 8. void cv::bitwise_or(InputArray src1, 9. InputArray src2, 10. OutputArray dst, 11. InputArray mask = noArray() 12. ) 13. //像素求异或运算 14. void cv::bitwise_xor(InputArray src1, 15. InputArray src2, 16. OutputArray dst, 17. InputArray mask = noArray() 18. ) 19. //像素求非运算 20. void cv::bitwise_not(InputArray src, 21. OutputArray dst, 22. InputArray mask = noArray() 23. )
-
src1:第一个图像矩阵,可以是多通道图像数据。
-
src2:第二个图像矩阵,尺寸和通道数以及数据类型都需要与src1一致。
-
dst:逻辑运算输出结果,尺寸和通道数和数据类型与src1一致。
-
mask:掩模,用于设置图像或矩阵中逻辑运算的范围。
这几个函数都执行相应的逻辑运算,在进行逻辑计算时,一定要保证两个图像矩阵之间的尺寸、数据类型和通道数相同,多个通道进行逻辑运算时不同通道之间是独立进行的。为了更加直观的理解两个图像像素间的逻辑运算,在代码清单3-16中给出两个黑白图像像素逻辑运算的示例程序,最后运行结果在图3-13中给出。
代码清单3-16 myLogicOperation.cpp两个图像像素逻辑运算 1. #include <opencv2\opencv.hpp> 2. #include <iostream> 3. #include <vector> 4. 5. using namespace std; 6. using namespace cv; 7. 8. int main() 9. { 10. Mat img = imread("lena.png"); 11. if (img.empty()) 12. { 13. cout << "请确认图像文件名称是否正确" << endl; 14. return -1; 15. } 16. //创建两个黑白图像 17. Mat img0 = Mat::zeros(200, 200, CV_8UC1); 18. Mat img1 = Mat::zeros(200, 200, CV_8UC1); 19. Rect rect0(50, 50, 100, 100); 20. img0(rect0) = Scalar(255); 21. Rect rect1(100, 100, 100, 100); 22. img1(rect1) = Scalar(255); 23. imshow("img0", img0); 24. imshow("img1", img1); 25. 26. //进行逻辑运算 27. Mat myAnd, myOr, myXor, myNot, imgNot; 28. bitwise_not(img0, myNot); 29. bitwise_and(img0, img1, myAnd); 30. bitwise_or(img0, img1, myOr); 31. bitwise_xor(img0, img1, myXor); 32. bitwise_not(img, imgNot); 33. imshow("myAnd", myAnd); 34. imshow("myOr", myOr); 35. imshow("myXor", myXor); 36. imshow("myNot", myNot); 37. imshow("img", img); 38. imshow("imgNot", imgNot); 39. waitKey(0); 40. return 0; 41. }