zoukankan      html  css  js  c++  java
  • 5.11实例应用

    5.11.1 颜色圆检测

    RGB:

    RGBA(Alpha),A用于描述三原色的透明度!

    单通道:

    俗称灰度图,每个像素点只能有一个值表示颜色,它的像素值在0到255之间,0是黑色,255是白色,中间值是一些不同等级的灰色,可以说灰度是黑与白之间的过渡色!

    多通道:

    多通道也就是RGB三原色,每个像素点有三个字节来表示(RGB),分别最大取值范围是0-255,可以组合成千万种颜色。

    所以三通道想要组合成黑白色(灰度)必须三原色值相同。也就是说灰度图不一定是单通道,但是单通道一定是灰度图!

    色调、饱和度、亮度(Hue, Saturation, Value):

    色调(偏向)

    色调决定一个像素点中的颜色更偏向于哪一方(RGB):

    饱和度(深浅):

    饱和度决定了颜色空间中颜色分量,饱和度越高,说明颜色越深,饱和度越低,说明颜色越浅!

    亮度(明暗):

    亮度决定颜色空间中颜色的明暗程度!

    RGB和HSV关系:

    其实色调,饱和度,亮度都是通过特定的算法经过计算修改RGB三色而达到的控制颜色效果!

    • 色调(H:hue):用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;
    • 饱和度(S:saturation):取值范围为0.0~1.0,值越大,颜色越饱和。
    • 亮度(V:value):取值范围为0(黑色)~255(白色)。

    参考:

    https://blog.csdn.net/bjbz_cxy/article/details/79701006

    OpenCV下有个函数可以直接将RGB模型转换为HSV模型,注意的是OpenCV中H∈ [0, 180), S ∈ [0, 255], V ∈ [0, 255]。 

    HoughCircles()使用比较关键是参数的设置

     1 ////////////https://blog.csdn.net/piaoxuezhong/article/details/60757278
     2 ////////找出圆绘制圆心和外圆
     3 #include <opencv2/opencv.hpp>
     4 #include <opencv2/imgproc/imgproc.hpp>
     5 
     6 using namespace cv;
     7 using namespace std;
     8 
     9 int main(int argc, char** argv)
    10 {
    11 
    12     Mat srcImage = imread("D:\1块硬币.jpg");
    13     Mat midImage, dstImage;
    14     imshow("【原始图】", srcImage);
    15 
    16     cvtColor(srcImage, midImage, CV_BGR2GRAY);//转化边缘检测后的图为灰度图
    17     GaussianBlur(midImage, midImage, Size(9, 9), 2, 2);
    18     vector<Vec3f> circles;
    19     HoughCircles(midImage, circles, CV_HOUGH_GRADIENT, 1, midImage.rows / 20, 100, 100, 0, 0);
    20     //依次在图中绘制出圆
    21     for (size_t i = 0; i < circles.size(); i++)
    22     {
    23         Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
    24         int radius = cvRound(circles[i][2]);
    25         //绘制圆心
    26         circle(srcImage, center, 3, Scalar(0, 255, 0), -1, 8, 0);
    27         //绘制圆轮廓
    28         circle(srcImage, center, radius, Scalar(155, 50, 255), 3, 8, 0);
    29     }
    30 
    31     imshow("【效果图】", srcImage);
    32     waitKey(0);
    33     return 0;
    34 }
    View Code

    第1张图片:

    第2张图片:

    参考:https://blog.csdn.net/piaoxuezhong/article/details/60757278

     1 ////////https://blog.csdn.net/linqianbi/article/details/78936612
     2 #include<opencv2highguihighgui.hpp>
     3 #include<opencv2imgprocimgproc.hpp>
     4 #include<iostream>
     5 #include<vector>
     6 using namespace cv;
     7 using namespace std;
     8 int main()
     9 {
    10     Mat srcImage = imread("D:\颜色圆.jpg");
    11     if (!srcImage.data)
    12     {
    13         printf("could not load image...
    ");
    14         return -1;
    15     }
    16     imshow("srcImage", srcImage);
    17     Mat resultImag = srcImage.clone();
    18     //中值滤波
    19     medianBlur(srcImage, srcImage, 3);
    20     //转换成HSV颜色空间
    21     Mat hsvImage;
    22     cvtColor(srcImage, hsvImage, CV_BGR2HSV);
    23     imshow("hsvImage", hsvImage);
    24     //颜色阈值化处理
    25     //定义高低阈值
    26     Mat lowMat;
    27     Mat upperMat;
    28     //红色H的范围是[0,10]  [160,180]
    29     inRange(hsvImage, Scalar(0, 100, 100), Scalar(10, 255, 255), lowMat);
    30     inRange(hsvImage, Scalar(160, 100, 100), Scalar(179, 255, 255), upperMat);
    31     imshow("lowMat", lowMat);
    32     imshow("upperMat", upperMat);
    33     //将高低阈值合并
    34     Mat redMat;
    35     addWeighted(lowMat, 1, upperMat, 1, 0, redMat);
    36     imshow("redMat", redMat);
    37     //高斯滤波
    38     GaussianBlur(redMat, redMat, Size(9, 9), 2, 2);
    39     //霍夫圆加测
    40     vector<Vec3f>  circles;
    41     HoughCircles(redMat, circles, CV_HOUGH_GRADIENT, 1, redMat.rows / 8, 100, 50, 0, 0);
    42     //如果没有检测到圆
    43     if (circles.size() == 0)
    44         return -1;
    45     for (int i = 0; i < circles.size(); i++)
    46     {
    47         //求出圆心的位置和圆半径的大小
    48         Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
    49         int radius = cvRound(circles[i][2]);
    50         circle(resultImag, center, radius, Scalar(0, 255, 0), 5);
    51     }
    52     imshow("resultImag", resultImag);
    53     waitKey(0);
    54     return 0;
    55 }
    View Code

    1.将原始图片的BGR颜色空间转换到HSV色彩空间

    2.根据红色在HSV中的范围,对图像进行阈值分割,红色的圆被保留(白色),其他的变成黑色

    3.对步骤二检测到的高低阈值的颜色圆进行合并,找出属于红色的圆

    4.利用霍夫圆检测算法找出步骤3中的圆

     

    拓展:

    如果要选中找出蓝色圆:

    需要一个取色和调色小工具,这个小工具支持HSV空间的取色。不过不管是这个小工具还是PS中,H的范围都是0~360,S的范围是0到百分之百,V的范围也是0到百度分之百,这个也和百科上的解释是一致的。所以你在具体使用的时候要按比例转化一下哦!比如车牌蓝在标准HSV中是(225,100%,81%)那么转换到OpenCV中就是(225/360*180,255*100%,255*81%)!

    参考:https://blog.csdn.net/wenhao_ir/article/details/51850948 

    下面是用HoughCircles函数进行霍夫变换圆检测的实例。由于HoughCircles函数内是调用Canny函数进行边缘检测,opencv的Canny函数是不包括平滑滤波这一步的,因此为了增强抗干扰能力,在使用HoughCircles函数之前,我们先对原图进行滤波处理,我们使用的是高斯模糊方法。 

     参考:

    https://blog.csdn.net/piaoxuezhong/article/details/60757278

    https://blog.csdn.net/linqianbi/article/details/78936612

    https://blog.csdn.net/poem_qianmo/article/details/26977557

    https://blog.csdn.net/yanxiaolx/article/details/62889943

    未研究:https://blog.csdn.net/taily_duan/article/details/51886019 

    http://www.opencv.org.cn/forum.php?mod=viewthread&tid=34096

    5.11.2 车牌区域检测

      1 ////////https://blog.csdn.net/z827997640/article/details/80527581
      2 
      3 #include <iostream>
      4 #include <vector>
      5 #include <stdint.h>
      6 #include "opencv2/core/core.hpp"
      7 #include "opencv2/highgui/highgui.hpp"
      8 #include "opencv2/imgproc/imgproc.hpp"
      9 #include "opencv2/features2d/features2d.hpp"
     10 // 提取竖直的sobel边缘
     11 bool SobelVerEdge(cv::Mat srcImage, cv::Mat& resultImage)
     12 {
     13     CV_Assert(srcImage.channels() == 1);
     14     srcImage.convertTo(srcImage, CV_32FC1);
     15     // 水平方向的 Sobel 算子
     16     cv::Mat sobelx = (cv::Mat_<float>(3, 3) << -0.125, 0, 0.125,
     17         -0.25, 0, 0.25,
     18         -0.125, 0, 0.125);
     19     cv::Mat ConResMat;
     20     // 卷积运算
     21     cv::filter2D(srcImage, ConResMat, srcImage.type(), sobelx);
     22     // 计算梯度的幅度
     23     cv::Mat graMagMat;
     24     cv::multiply(ConResMat, ConResMat, graMagMat);
     25     // 根据梯度幅度及参数设置阈值
     26     int scaleVal = 4;
     27     double thresh = scaleVal * cv::mean(graMagMat).val[0];
     28     cv::Mat resultTempMat = cv::Mat::zeros(
     29         graMagMat.size(), graMagMat.type());
     30     float* pDataMag = (float*)graMagMat.data;
     31     float* pDataRes = (float*)resultTempMat.data;
     32     const int nRows = ConResMat.rows;
     33     const int nCols = ConResMat.cols;
     34     for (int i = 1; i != nRows - 1; ++i) {
     35         for (int j = 1; j != nCols - 1; ++j) {
     36             // 计算该点梯度与水平或垂直梯度值大小比较结果
     37             bool b1 = (pDataMag[i * nCols + j] > pDataMag[i *
     38                 nCols + j - 1]);
     39             bool b2 = (pDataMag[i * nCols + j] > pDataMag[i *
     40                 nCols + j + 1]);
     41             bool b3 = (pDataMag[i * nCols + j] > pDataMag[(i - 1)
     42                 * nCols + j]);
     43             bool b4 = (pDataMag[i * nCols + j] > pDataMag[(i + 1)
     44                 * nCols + j]);
     45             // 判断邻域梯度是否满足大于水平或垂直梯度
     46             // 并根据自适应阈值参数进行二值化
     47             pDataRes[i * nCols + j] = 255 * ((pDataMag[i *
     48                 nCols + j] > thresh) &&
     49                 ((b1 && b2) || (b3 && b4)));
     50         }
     51     }
     52     resultTempMat.convertTo(resultTempMat, CV_8UC1);
     53     resultImage = resultTempMat.clone();
     54     return true;
     55 }
     56 // 疑似区域提取
     57 cv::Mat getPlateArea(cv::Mat srcImage, cv::Mat sobelMat)
     58 {
     59     // 转换成hsv 
     60     cv::Mat img_h, img_s, img_v, imghsv;
     61     std::vector<cv::Mat> hsv_vec;
     62     cv::cvtColor(srcImage, imghsv, CV_BGR2HSV);
     63     cv::imshow("hsv", imghsv);
     64     cv::waitKey(0);
     65     // 分割hsv通道
     66     cv::split(imghsv, hsv_vec);
     67     img_h = hsv_vec[0];
     68     img_s = hsv_vec[1];
     69     img_v = hsv_vec[2];
     70     img_h.convertTo(img_h, CV_32F);
     71     img_s.convertTo(img_s, CV_32F);
     72     img_v.convertTo(img_v, CV_32F);
     73     double max_s, max_h, max_v;
     74     cv::minMaxIdx(img_h, 0, &max_h);
     75     cv::minMaxIdx(img_s, 0, &max_s);
     76     cv::minMaxIdx(img_v, 0, &max_v);
     77     // 各个通道归一化
     78     img_h /= max_h;
     79     img_s /= max_s;
     80     img_v /= max_v;
     81     // hsv 限定范围元素提取
     82     cv::Mat bw_blue = ((img_h>0.45) &
     83         (img_h<0.75) &
     84         (img_s>0.15) &
     85         (img_v>0.25));
     86     int height = bw_blue.rows;
     87     int width = bw_blue.cols;
     88     cv::Mat bw_blue_edge = cv::Mat::zeros(bw_blue.size(), bw_blue.type());
     89     cv::imshow("bw_blue", bw_blue);
     90     cv::waitKey(0);
     91     // 车牌疑似区域提取
     92     for (int k = 1; k != height - 2; ++k)
     93     {
     94         for (int l = 1; l != width - 2; ++l)
     95         {
     96             cv::Rect rct;
     97             rct.x = l - 1;
     98             rct.y = k - 1;
     99             rct.height = 3;
    100             rct.width = 3;
    101             if ((sobelMat.at<uchar>(k, l) == 255) && (cv::countNonZero(bw_blue(rct)) >= 1))
    102                 bw_blue_edge.at<uchar>(k, l) = 255;
    103         }
    104     }
    105     // 形态学闭操作
    106     cv::Mat morph;
    107     cv::morphologyEx(bw_blue_edge, morph, cv::MORPH_CLOSE,
    108         cv::Mat::ones(2, 25, CV_8UC1));
    109     cv::Mat imshow5;
    110     cv::resize(bw_blue_edge, imshow5, cv::Size(), 1, 1);
    111     cv::imshow("morphology_bw_blue_edge", imshow5);
    112     cv::waitKey(0);
    113     // 连通区域提取
    114     cv::imshow("morph", morph);
    115     std::vector<std::vector<cv::Point> > region_contours;
    116     cv::findContours(morph.clone(), region_contours,
    117         CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
    118     std::vector<cv::Rect> candidates;
    119     std::vector<cv::Mat> candidates_img;
    120     cv::Mat result;
    121     for (size_t n = 0; n != region_contours.size(); ++n)
    122     {
    123         // 去除高度宽度不符合条件区域
    124         cv::Rect rect = cv::boundingRect(region_contours[n]);
    125         int sub = cv::countNonZero(morph(rect));
    126         double ratio = double(sub) / rect.area();
    127         double wh_ratio = double(rect.width) / rect.height;
    128         if (ratio > 0.5 && wh_ratio > 2 && wh_ratio < 5 &&
    129             rect.height > 12 && rect.width > 60)
    130         {
    131             cv::Mat small = bw_blue_edge(rect);
    132             result = srcImage(rect);
    133             cv::imshow("rect", srcImage(rect));
    134             cv::waitKey(0);
    135         }
    136     }
    137     return result;
    138 }
    139 int main()
    140 {
    141     cv::Mat srcImage = cv::imread("D:\车辆4.jpg");
    142     if (!srcImage.data)
    143         return 1;
    144     cv::Mat srcGray;
    145     cv::cvtColor(srcImage, srcGray, CV_RGB2GRAY);
    146     cv::imshow("srcImage", srcImage);
    147     // sobel 提取边缘
    148     cv::Mat sobelMat;
    149     SobelVerEdge(srcGray, sobelMat);
    150     cv::imshow("Sobel", sobelMat);
    151     // 疑似区域提取
    152     cv::Mat result = getPlateArea(srcImage, sobelMat);
    153     cv::imshow("result", result);
    154     return 0;
    155 }
    View Code

      1 ////////https://blog.csdn.net/hust_bochu_xuchao/article/details/52230694
      2 ////////第4章图片“车辆4”才识别出车牌
      3 #include "opencv2/highgui/highgui.hpp"
      4 #include "opencv2/features2d.hpp"
      5 #include "opencv2/imgproc/imgproc.hpp"
      6 #include <iostream>
      7 // Mser车牌目标检测
      8 std::vector<cv::Rect> mserGetPlate(cv::Mat srcImage)
      9 {
     10     // HSV空间转换
     11     cv::Mat gray, gray_neg;
     12     cv::Mat hsi;
     13     cv::cvtColor(srcImage, hsi, CV_BGR2HSV);
     14     // 通道分离
     15     std::vector<cv::Mat> channels;
     16     cv::split(hsi, channels);
     17     // 提取h通道
     18     gray = channels[1];
     19     cv::imshow("提取h通道", gray);
     20     // 灰度转换 
     21     cv::cvtColor(srcImage, gray, CV_BGR2GRAY);
     22     // 取反值灰度
     23     gray_neg = 255 - gray;
     24     std::vector<std::vector<cv::Point> > regContours;
     25     std::vector<std::vector<cv::Point> > charContours;
     26 
     27     // 创建MSER对象
     28     cv::Ptr<cv::MSER> mesr1 = cv::MSER::create(2, 10, 5000, 0.5, 0.3);
     29     cv::Ptr<cv::MSER> mesr2 = cv::MSER::create(2, 2, 400, 0.1, 0.3);
     30 
     31 
     32     std::vector<cv::Rect> bboxes1;
     33     std::vector<cv::Rect> bboxes2;
     34     // MSER+ 检测
     35     mesr1->detectRegions(gray, regContours, bboxes1);
     36     // MSER-操作
     37     mesr2->detectRegions(gray_neg, charContours, bboxes2);
     38 
     39     cv::Mat mserMapMat = cv::Mat::zeros(srcImage.size(), CV_8UC1);
     40     cv::Mat mserNegMapMat = cv::Mat::zeros(srcImage.size(), CV_8UC1);
     41 
     42     for (int i = (int)regContours.size() - 1; i >= 0; i--)
     43     {
     44         // 根据检测区域点生成mser+结果
     45         const std::vector<cv::Point>& r = regContours[i];
     46         for (int j = 0; j < (int)r.size(); j++)
     47         {
     48             cv::Point pt = r[j];
     49             mserMapMat.at<unsigned char>(pt) = 255;
     50         }
     51     }
     52     // MSER- 检测
     53     for (int i = (int)charContours.size() - 1; i >= 0; i--)
     54     {
     55         // 根据检测区域点生成mser-结果
     56         const std::vector<cv::Point>& r = charContours[i];
     57         for (int j = 0; j < (int)r.size(); j++)
     58         {
     59             cv::Point pt = r[j];
     60             mserNegMapMat.at<unsigned char>(pt) = 255;
     61         }
     62     }
     63     // mser结果输出
     64     cv::Mat mserResMat;
     65     // mser+与mser-位与操作
     66     mserResMat = mserMapMat & mserNegMapMat;
     67     cv::imshow("mserMapMat", mserMapMat);
     68     cv::imshow("mserNegMapMat", mserNegMapMat);
     69     cv::imshow("mserResMat", mserResMat);
     70     // 闭操作连接缝隙
     71     cv::Mat mserClosedMat;
     72     cv::morphologyEx(mserResMat, mserClosedMat,
     73         cv::MORPH_CLOSE, cv::Mat::ones(1, 20, CV_8UC1));
     74     cv::imshow("mserClosedMat", mserClosedMat);
     75     // 寻找外部轮廓
     76     std::vector<std::vector<cv::Point> > plate_contours;
     77     cv::findContours(mserClosedMat, plate_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
     78     // 候选车牌区域判断输出
     79     std::vector<cv::Rect> candidates;
     80     for (size_t i = 0; i != plate_contours.size(); ++i)
     81     {
     82         // 求解最小外界矩形
     83         cv::Rect rect = cv::boundingRect(plate_contours[i]);
     84         // 宽高比例
     85         double wh_ratio = rect.width / double(rect.height);
     86         // 不符合尺寸条件判断
     87         if (rect.height > 20 && wh_ratio > 4 && wh_ratio < 7)
     88             candidates.push_back(rect);
     89     }
     90     return  candidates;
     91 }
     92 int main()
     93 {
     94     cv::Mat srcImage = cv::imread("D:\车辆4.jpg");
     95     if (srcImage.empty())
     96         return-1;
     97     cv::imshow("src Image", srcImage);
     98     // 候选车牌区域检测
     99     std::vector<cv::Rect> candidates;
    100     candidates = mserGetPlate(srcImage);
    101     // 车牌区域显示
    102     for (int i = 0; i < candidates.size(); ++i)
    103     {
    104         cv::imshow("rect", srcImage(candidates[i]));
    105         cv::waitKey();
    106     }
    107     cv::waitKey(0);
    108     return 0;
    109 }
    View Code

  • 相关阅读:
    【IDEA】IDEA自定义注解无法自动识别入参和出参
    vue脚手架安装成功,但依然提示'vue' 不是内部或外部命令,也不是可运行的程序 或批处理文件。解决方案
    小程序怎么将input宽输入字母全部转大写字母
    微信小程序van-popup左右弹窗无法显示白色背景
    vscode中实现滚轮缩放代码
    element-ui监听el-dialog关闭事件
    测试人必看的5本好书,没看过你就吃亏啦~
    解决Access在Windows7下数据源的配置问题(32位)
    微软Win10补丁KB5005565更新后打印机连接不上(0x0000011b)
    Windows设置共享文件夹无法访问问题
  • 原文地址:https://www.cnblogs.com/thebreakofdawn/p/9535654.html
Copyright © 2011-2022 走看看