C++ Opencv图像处理学习

图像读取与显示
  // 读取图片
    Mat img;
    string img_path = "C:\\Users\\my_file\\Desktop\\data\\4.bmp";
    img = imread(img_path);
    if (img.empty())
    {
        cout << "请确认图像文件名是否正确" << endl;
        return 0;
    }
    else
    {
        cout << "图片读取成功!" << endl;
    }

    // 显示根据原图片大小生成窗口
    int img_height;
    int img_width;
    img_height = img.cols;   // 获取图片的行和列
    img_width = img.rows;
    printf("图片的高度%d\n", img_height);
    printf("图片的宽度%d\n", img_width);
    //   namedWindow("原图",0);  //创建窗口

// 因显示不全所以缩放
    Mat resized_down;
    resize(img, resized_down, Size(img_width, img_height), INTER_LINEAR);

图像预处理–灰度化二值化

// ----------------------------------------------------图像预处理-------------------------------------------------------------
 // 
         // 灰度化 -> 二值化 -> 去噪 -> 边缘检测 ->  
         // 1.灰度化并显示
    Mat img_2_gray;
    Mat img_2_gray_rd;
    namedWindow("灰度图", 0);       //创建窗口
    // namedWindow("9x9滤波灰度图", 0);

    cvtColor(img, img_2_gray, COLOR_BGR2GRAY);
    resize(img_2_gray, img_2_gray_rd, Size(img_2_gray.rows, img_2_gray.cols), INTER_LINEAR);
    imshow("灰度图", img_2_gray_rd);
    waitKey(0);

    Mat  bin_img, bin_img_rd;
    threshold(img_2_gray, bin_img, 0, 255, 0 | THRESH_OTSU); //二值化
    namedWindow("二值化后图像", 0);
    resize(bin_img, bin_img_rd, Size(bin_img.rows, bin_img.cols), INTER_LINEAR);
    imshow("二值化后图像", bin_img_rd);
    waitKey(0);

图像预处理–去噪

  // 2.去噪 -------------------------------------------中值滤波------------------------------------------------------------

    Mat  grayResult9, grayResult9_rd;

    medianBlur(bin_img, grayResult9, 9);
    namedWindow("9x9滤波灰度图", 0);
    resize(grayResult9, grayResult9_rd, Size(grayResult9.rows, grayResult9.cols), INTER_LINEAR);
    imshow("9x9滤波灰度图", grayResult9_rd);
    waitKey(0);


    // 内核
    Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
    int cl_iterations = 1;   // 设置闭运算次数为4次

    // 进行-------------------------------------------------闭运算------------------------------------------------------------


    Mat closedImage, closedImage_rd;
    morphologyEx(grayResult9, closedImage, MORPH_CLOSE, kernel, Point(-1, -1), cl_iterations);
    namedWindow("闭运算结果图", 0);
    resize(closedImage, closedImage_rd, Size(closedImage.rows, closedImage.cols), INTER_LINEAR);
    imshow("闭运算结果图", closedImage_rd);
    waitKey(0);

边缘检测

使用canny算子

 // 3.--------------------------------------------------边缘检测-----------------------------------------------------------


    // 边缘检测
    Mat cannyout, cannyout_rd;
    Canny(closedImage, cannyout, thresh, thresh * 2, 3);          // y一般为1:2或1:3
    namedWindow("边缘检测结果图", 0);
    resize(cannyout, cannyout_rd, Size(cannyout.rows, cannyout.cols), INTER_LINEAR);
    imshow("边缘检测结果图", cannyout);
    // String filename = "边缘检测.jpg";
   // imwrite(filename, cannyout);
    waitKey(0);

边缘检测以及轮廓绘制

为了生成掩膜图,绘制轮廓时绘制最外层轮廓,将层级低的轮廓过滤掉

   //------------------------------------------------------轮廓绘制---------------------------------------------------------

    vector<vector<Point>> contours, Contours_temp;   //
    double con_area;                  // 存放轮廓面积
    vector<Vec4i> hierarchy;          // 存放轮廓层次
    // 创建一个空白的图像来绘制轮廓

     // 提取轮廓

    Mat contourImage = Mat::zeros(img.size(), CV_8UC3);

    findContours(cannyout, Contours_temp, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); // 查找全部的轮廓
   // findContours(cannyout, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE); // 查找全部的轮廓
    printf("find %d contours", Contours_temp.size());

    // 4.绘制原始轮廓
    drawMyContours("未筛选轮廓图", img, Contours_temp, true);
  //   String filename1 = "未筛选轮廓图.jpg";
  //  imwrite(filename1, img);

    // 5.筛选轮廓
    // 初始化迭代器
    //vector<vector<Point>>::iterator itc = contours.begin();
    //vector<Vec4i>::iterator itc_hierarchy = hierarchy.begin();
    //  5.1使用层级结构筛选轮廓
    //int i = 0;
    //while (itc_hierarchy != hierarchy.end())
    //{
    //    //验证轮廓大小
    //    if (hierarchy[i][2] > 0 || hierarchy[i][3] > 0) // 存在子轮廓/父轮廓
    //    {
    //        itc = contours.erase(itc);
    //        itc_hierarchy = hierarchy.erase(itc_hierarchy);
    //    }
    //    else
    //    {
    //        ++i;
    //        ++itc;
    //        ++itc_hierarchy;
    //    }
    //}
        
    printf("%d contours remaining after hierarchy filtering\n", Contours_temp.size());

    for (size_t t = 0; t < Contours_temp.size(); t++)
    {
       // 计算轮廓面积
       double area = contourArea(Contours_temp[t]);
      // cout << "Contour " << t << " Area: " << area << endl;
       if (area > 200)    //500
       {
           contours.push_back(Contours_temp[t]);
           
       }
    }
    // 绘制级别筛选后的轮廓
    drawMyContours("绘制最外层轮廓", img, contours, true);
  //  String filename2 = "最外层轮廓.jpg";
  //  imwrite(filename2, img);

生成掩膜图

绘制好轮廓后将轮廓内部填充为一个灰度值,掩膜和背景区分开来

   //-------------------------------------------------------掩膜填充-------------------------------------------------------

    // 初始化Mat 掩膜容器
    Mat mask = Mat::zeros(img.size(), CV_8UC1);
    Mat mask_rd;
    Mat mask_small = Mat::zeros(img.size(), CV_8UC1);
    Mat mask_small_rd;
    Mat mask_large = Mat::zeros(img.size(), CV_8UC1);
    Mat mask_large_rd;
    Mat mask_largeround = Mat::zeros(img.size(), CV_8UC1);
    Mat mask_largeround_rd;

    Mat normmask = Mat::zeros(img.size(), CV_8UC1);
    Mat normmask_rd;

    Mat count;    // 存储抠图

   //  裁图
   /* for (size_t t = 0; t < contours.size(); t++)
    {
        
        Mat tempImage = Mat::zeros(img.size(), img.type());

        
        drawContours(tempImage, contours, t, Scalar(255, 255, 255), -1);

        // 使用掩膜图(tempImage)提取原始图像中的区域
        Mat maskedRegion;
        img.copyTo(maskedRegion, tempImage);

        // 保存裁剪后的单个图像
        
        String filename = "cropped_image_" + std::to_string(t) + ".jpg";
        count = t;
        imwrite(filename, maskedRegion);
    }*/

     // 填充轮廓
    for (size_t t = 0; t < contours.size(); t++)
    {
        drawContours(mask, contours, t, Scalar(255, 225, 225), -1); // FILLED 与-1等同
    }

  //  String filename3 = "填充轮廓-掩膜图.jpg";
  //  imwrite(filename3, mask);

    namedWindow("填充轮廓-掩膜图", 0);
    resize(mask, mask_rd, Size(mask.rows, mask.cols), INTER_LINEAR);
    imshow("填充轮廓-掩膜图", mask_rd);
    waitKey(0);

根据轮廓特征分类并抠图

抠图就需要将掩膜图放在原图上push_back

   //----------------------------------------------------通过设置阈值分类----------------------------------------------------

    vector<vector<Point>> smallContours;         // 体积过小轮廓
    vector<vector<Point>> largeContours;         // 粘连轮廓
    vector<vector<Point>> largeroundContours;    // 圆型体积大轮廓

    vector<vector<Point>> normalContours;        // 正常

    vector<double>area;                          // 面积
    vector<double>roundness;                     // 圆形度
    vector<double>len;                           // 周长

    // 区分
    for (size_t t = 0; t < contours.size(); t++)
    {
        // 计算面积和周长
        double con_area = contourArea(contours[t]);
        double con_len = arcLength(contours[t], true);
        double con_round = (4 * CV_PI * con_area) / (con_len * con_len);

        area.push_back(con_area);
        len.push_back(con_len);
        roundness.push_back(con_round);

        int class_num;

        cout << "contour " << t << " Area: " << area[t] << endl;
        cout << "contour " << t << " Perimeter: " << len[t] << endl;
        cout << "contour " << t << " Roundness: " << roundness[t] << endl;
        // 高斯分布
        if (area[t] < 12000 && roundness[t] < 0.8820)                // 体积过小 包含形状不规则
        {
            class_num = 0;
            add_key_to_pilldata(mysql, area[t], class_num);
            smallContours.push_back(contours[t]);

        }
        else if (area[t] > 20000 && len[t] > 550 && roundness[t] < 0.8)           // 粘连
        {
            class_num = 0;
            add_key_to_pilldata(mysql, area[t], class_num);
            largeContours.push_back(contours[t]);
        }
        else if (area[t] > 14000 && len[t] > 470 && roundness[t] >= 0.78)        // 体积过大圆形
        {
            class_num = 0;
            add_key_to_pilldata(mysql, area[t], class_num);
            largeroundContours.push_back(contours[t]);
        }
        else
        {
            class_num = 1;
            add_key_to_pilldata(mysql, area[t], class_num);
            normalContours.push_back(contours[t]);
        }

        //if ((area[t] > 11000 && area[t] < 14000 ) && (roundness[t] > 0.80 && roundness[t] <= 0.9))
        //{
        //    normalContours.push_back(contours[t]);
        //}
        //else if (area[t] < 11000  )
        //{
        //    smallContours.push_back(contours[t]);
        //}
        //else if (area[t] > 12000)
        //{
        //    largeroundContours.push_back(contours[t]);
        //}

    }
    getchar();
 

    //for (size_t t = 0; t < normalContours.size(); t++)
    //{
    //    double con_area = contourArea(contours[t]);
    //    double con_len = arcLength(contours[t], true);
    //    double con_round = (4 * CV_PI * con_area) / (con_len * con_len);

  

    // 归类

    for (size_t t = 0; t < smallContours.size(); t++)
    {
        
        drawContours(mask_small, smallContours, t, Scalar(255, 225, 225), -1); // FILLED 与-1等同

    }

  //  String filename4 = "体积过小药丸掩膜图.jpg";
  //  imwrite(filename4, mask_small);

    namedWindow("体积过小掩膜图", 0);
    resize(mask_small, mask_small_rd, Size(mask_small.rows, mask_small.cols), INTER_LINEAR);
    imshow("体积过小掩膜图", mask_small_rd);
    waitKey(0);

    for (size_t t = 0; t < largeContours.size(); t++)
    {
       
        drawContours(mask_large, largeContours, t, Scalar(255, 225, 225), -1); // FILLED 与-1等同
    }

  //  String filename5 = "粘连药丸掩膜图.jpg";
 //   imwrite(filename5, mask_large);

    namedWindow("粘连掩膜图", 0);
    resize(mask_large, mask_large_rd, Size(mask_large.rows, mask_large.cols), INTER_LINEAR);
    imshow("粘连掩膜图", mask_large_rd);

    for (size_t t = 0; t < normalContours.size(); t++)
    {
        
        drawContours(normmask, normalContours, t, Scalar(255, 225, 225), -1); // FILLED 与-1等同
    }

  //  String filename6 = "圆形大药丸掩膜图.jpg";
  //  imwrite(filename6, mask_largeround);

    namedWindow("正常掩膜图", 0);
    resize(normmask, normmask_rd, Size(normmask.rows, normmask.cols), INTER_LINEAR);
    imshow("正常掩膜图", normmask_rd);


    for (size_t t = 0; t < largeroundContours.size(); t++)
    {
        
        drawContours(mask_largeround, largeroundContours, t, Scalar(255, 225, 225), -1); // FILLED 与-1等同
    }

    //  String filename6 = "圆形大药丸掩膜图.jpg";
    //  imwrite(filename6, mask_largeround);

    namedWindow("圆形掩膜图", 0);
    resize(mask_largeround, mask_largeround_rd, Size(mask_largeround.rows, mask_largeround.cols), INTER_LINEAR);
    imshow("圆形掩膜图", mask_largeround_rd);

    // 抠分完类的图------粘连
    Mat nianimg;              
    Mat nianimg_rd;
    img.copyTo(nianimg, mask_large);

    namedWindow("粘连抠图", 0);
    resize(nianimg, nianimg_rd, Size(nianimg.rows, nianimg.cols), INTER_LINEAR);
    imshow("粘连抠图", nianimg_rd);


    //
    Mat largeround_img;
    Mat largeround_img_rd;
    img.copyTo(largeround_img, mask_largeround);

    namedWindow("圆形大抠图", 0);
    resize(largeround_img, largeround_img_rd, Size(largeround_img.rows, largeround_img.cols), INTER_LINEAR);
    imshow("圆形大抠图", largeround_img_rd);

    Mat small_img;
    Mat small_img_rd;
    img.copyTo(small_img, mask_small);

    namedWindow("体积过小抠图", 0);
    resize(small_img, small_img_rd, Size(small_img.rows, small_img.cols), INTER_LINEAR);
    imshow("体积过小抠图", small_img_rd);

    Mat normal_img;
    Mat normal_img_rd;
    img.copyTo(normal_img, normmask);

    namedWindow("正常抠图", 0);
    resize(normal_img, normal_img_rd, Size(normal_img.rows, normal_img.cols), INTER_LINEAR);
    imshow("正常抠图", normal_img_rd);

  //  String filename7 = "体积小药丸抠图.jpg";
  //  imwrite(filename7, small_img);

    // 保存
   // String filename = "粘连.jpg";
   // imwrite(filename, nianimg);
    waitKey(0);
    return 0;
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++ OpenCV是一种常用的图像处理库,可以用来进行图像的加载、修改和保存等操作。通过使用OpenCV的函数和方法,可以实现对图像的掩膜操作、对比度调整、均衡化以及形态学操作等。 例如,可以使用imread函数加载图像,如下所示: ```cpp Mat src = imread("C:\\Users\\td\\Desktop\\he.jpeg"); ``` 然后,可以使用cvtColor函数将图像转换为指定的色彩空间,例如将BGR色彩空间转换为BGR555色彩空间: ```cpp Mat output; cvtColor(src, output,CV_BGR2BGR555); ``` 接下来,可以使用imwrite函数保存修改后的图像: ```cpp imwrite("D:/zhubajie.png", output); ``` 除了图像加载和保存,还可以进行其他图像处理操作。例如,可以使用equalizeHist函数对图像进行均衡化处理: ```cpp cvtColor(src, src, CV_BGR2GRAY); Mat dst; equalizeHist(src, dst); ``` 还可以使用morphologyEx函数进行形态学操作,如开操作、闭操作、梯度操作等。例如,可以使用getStructuringElement函数创建结构元素,并通过morphologyEx函数对图像进行黑帽操作: ```cpp Mat kernel = getStructuringElement(MORPH_RECT, Size(11, 11), Point(-1, -1)); morphologyEx(src, dst, CV_MOP_BLACKHAT, kernel); ``` 以上是C++ OpenCV图像处理的一些基本操作,根据实际需求可以使用不同的函数和方法来完成不同的图像处理任务。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值