• 7--OpenCV:图像基本操作之①截取②掩膜 操作


    一、图像截取

    1.什么是ROI

    感兴趣区域(ROI,region of interest),就是从图像中选择的一个图像区域,这个区域是图像分许所关注的重点,通过圈定这个区域,一边进一步的处理,而且使用ROI指定想读入的目标,可以减少处理时间,增加精度。

    2.Rect截取ROI

    1. Rect::Rect(int x, int y, int width, int height);
    2. /*******************************************************************
    3. * x: 左上角x坐标
    4. * y: 左上角y坐标
    5. * width: 宽度
    6. * height: 高度
    7. *********************************************************************/
    8. Mat roi= img(Rect(x, y, w, h));

    3.Range截取ROI

            参数是按照行和列进行划分的。

                    第一个range的两个参数分别是起点的row和终点的row。

                    第二个range的两个参数分别是起点的col和终点的col

    1. Range::Range(int _start, int _end) ;
    2. /*******************************************************************
    3. * _start: 起点
    4. * _end: 终点
    5. *********************************************************************/
    6. Mat roi= img(Range(x,xx),Range(y,yy));

    4.selectROI截取ROI

            封装了三个操作如下

    1. Rect selectROI(InputArray img, bool showCrosshair = true, bool fromCenter = false);
    2. /*******************************************************************
    3. * img: 原图
    4. * showCrosshair: 鼠标选框,是否显示十字线
    5. * fromCenter: 是否以起始鼠标位置为中心
    6. *********************************************************************/
    7. //Rect rect= selectROI(img, false, false);
    8. //1.显示img
    9. //2.鼠标选择区域
    10. //3.使用“空格”或“enter”来完成当前选择并开始一个新的选择,使用“esc”终止多个ROI选择过程  
    11. void selectROIs(const String& windowName, InputArray img,CV_OUT std::vector& boundingBoxes, bool showCrosshair = true, bool fromCenter = false);

    5.综合代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. using namespace cv;
    7. class ROI
    8. {
    9. public:
    10. ROI() :img(imread("mm.jpg"))
    11. {
    12. roi["原图"] = img;
    13. }
    14. void GetRoiByRect(int x = 100, int y = 0, int w = 350, int h = 375)
    15. {
    16. roi["rect"] = img(Rect(x, y, w, h));
    17. }
    18. void GetRoiByRange()
    19. {
    20. roi["range"] = img(Range(0, img.rows), Range(100, 100 + 350));
    21. }
    22. void GetRoiBySelectROI()
    23. {
    24. Rect  rect = selectROI(img, false, true);
    25. //1.显示img
    26. //2.封装鼠标操作,支持手动选区
    27. //3.按回车或者esc退出
    28. roi["select"] = img(rect);
    29. }
    30. void Show()
    31. {
    32. for (auto& v : roi)
    33. {
    34. imshow(v.first, v.second);
    35. }
    36. waitKey(0);
    37. }
    38. private:
    39. //封装一个插入函数,作为截取图像插入roi容器方式
    40. //void InsertROI(string imgName, Mat img)
    41. //{
    42. // //roi.insert(pair(imgName, img));
    43. // roi[imgName] = img;
    44. //}
    45. Mat img;
    46. map roi;
    47. };
    48. int main()
    49. {
    50. ROI* proi = new ROI;
    51. proi->GetRoiByRange();
    52. proi->GetRoiByRect();
    53. proi->GetRoiBySelectROI();
    54. proi->Show();
    55. return 0;
    56. }

    二、图像掩膜操作

    1.什么是掩膜操作

    用一个矩阵和原图像作卷积操作,重新计算像素值,用数学术语讲,即我们自定义一个权重表

    • 掩模矩阵

    • 计算公式

    掩膜操作可以提高图像对比度,对比度提高可以增加图像感官度、锐化,让看起来有点模糊的图像更清晰

    2.像素读写实现掩膜操作

    注意:

            ①定义rows的时候,是img的rows-1--->防止越界(因为要访问next) 周围的四个像素

            ②定义cols的时候,是img的cols-1

            ③注意像素点ptr的函数的使用,获取像素数组

            ④saturate_cast防止像素值越界

    1. Mat mask = Mat::zeros(img.size(), img.type());
    2. int dims = img.channels();
    3. int rows = img.rows - 1;
    4. int cols = (img.cols - 1) * dims;
    5. for (int i = 1; i < rows; i++)
    6. {
    7. uchar* pre = img.ptr(i - 1);
    8. uchar* cur = img.ptr(i);
    9. uchar* next = img.ptr(i + 1);
    10. uchar* output = mask.ptr(i);
    11. for (int j = dims; j < cols; j++)
    12. {
    13. output[j] = saturate_cast(
    14. 5 * pre[j] - cur[j - dims] - cur[j + dims] - pre[j]- next[j]);
    15. }
    16. }

    3.filter2D实现掩膜操作

    需要定义一个权重矩阵:具体定义方法见下,Mat_(3,3)<<九个参数值

    1. //定义掩膜矩阵
    2. Mat dst;
    3. Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
    4. filter2D(img, dst, img.depth(), kernel);
    5. /*******************************************************************
    6. * img: 原图
    7. * dst: 存储结果图
    8. * img.depth(): 原图深度
    9. * kernel: 掩膜矩阵
    10. *********************************************************************/

    4.综合代码

    filter2D和自己操作像素得到的结果差不多。嫌麻烦可以直接fliter2D

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. using namespace cv;
    7. class Mask
    8. {
    9. public:
    10. Mask() :img(imread("mm.jpg"))
    11. {
    12. mask["原图"] = img;
    13. }
    14. void Mask_filter2D()
    15. {
    16. Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
    17. filter2D(img, mask["filter2D"], img.depth(), kernel);
    18. }
    19. void Mask_pixel()
    20. {
    21. mask["pixel"] = Mat::zeros(img.size(), img.type());
    22. int dims = img.channels();
    23. int rows = img.rows - 1;
    24. int cols = (img.cols - 1) * dims;
    25. for (int i = 1; i < rows; i++)
    26. {
    27. uchar* pre = img.ptr(i - 1); //上一行
    28. uchar* cur = img.ptr(i); //当前行
    29. uchar* next = img.ptr(i + 1); //下一行
    30. uchar* output = mask["pixel"].ptr(i);
    31. for (int j = dims; j < cols; j++)
    32. {
    33. output[j] = saturate_cast(5 * cur[j] - cur[j - dims] - cur[j + dims] - pre[j] - next[j]);
    34. }
    35. }
    36. }
    37. void Show()
    38. {
    39. for (auto& v : mask)
    40. {
    41. imshow(v.first, v.second);
    42. }
    43. waitKey(0);
    44. }
    45. private:
    46. Mat img;
    47. map mask;
    48. };
    49. int main()
    50. {
    51. Mask* pmask = new Mask;
    52. pmask->Mask_pixel();
    53. pmask->Mask_filter2D();
    54. pmask->Show();
    55. return 0;
    56. }

            效果图:

  • 相关阅读:
    仿函数c++
    Win命令行CMD常用命令大全
    用Blender制作YOLO目标检测器训练数据
    JCJC-基于剪贴板的碎片信息收集工具
    基于vue和nodejs毕业设计酒店预约管理系统
    AIE荧光性质温温敏性水凝胶纳米微球PS-co-PNIPAM/银纳米团簇与吡啶羧酸AIE水凝胶的制备
    【Ubuntu】Systemctl控制nacos启动与关闭
    春秋云镜 CVE-2014-3704
    LeetCode:1465. 切割后面积最大的蛋糕(C++)
    实验6 8255并行接口实验【微机原理】【实验】
  • 原文地址:https://blog.csdn.net/zjjaibc/article/details/126545842