• 斑点检测


         参考:http://blog.csdn.net/abcd1992719g/article/details/27071273

                 http://www.cnblogs.com/ronny/p/3895883.html#3036526

                这两位博主都实现了这个算法,里面有很多细节,还是很有收获的。

               

    #include "opencv2/core/core.hpp"
    #include "opencv2/features2d/features2d.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/calib3d/calib3d.hpp"
    #include "opencv2/nonfree/nonfree.hpp"
    #include<opencv2/highgui/highgui.hpp>
    #include<opencv2/imgproc/imgproc.hpp>
    #include <iostream>
    using namespace cv;
    using namespace std;
    
    /******************************Blob特征实现**********************************************/
    
    /*****生成log sigma******/
    vector<double> create_sigma(double start, double step, double end)
    {
        vector<double> sigma;
        while (start <= end + 1e-8)
        {
            double s = exp(start);
            sigma.push_back(s);
            start += step;
        }
    
        return sigma;
    }
    
    /********生成log算子模板************/
    Mat create_LOG(int size, double sigma)
    {
        Mat H(size, size, CV_64F);
        int cx = (size - 1) / 2;
        int cy = (size - 1) / 2;
        double sum = 0;
        for (int i = 0; i < H.rows; i++)
        {
            for (int j = 0; j < H.cols; j++)
            {
                int nx = i - cx;
                int ny = j - cy;
                double s = -1 / (3.1415926 * sigma*sigma*sigma*sigma);
                s = s* (1 - (nx*nx + ny*ny) / (2 * sigma*sigma));
                s = s*exp(-(nx*nx + ny*ny) / (2 * sigma*sigma));
                sum += s;
                H.at<double>(i, j) = s;
            }
        }
        double mean = sum / (size*size);
        for (int i = 0; i < H.rows; i++)
        {
            for (int j = 0; j < H.cols; j++)
                H.at<double>(i, j) -= mean;
        }
    
        return H;
    }
    
    struct blob
    {
        int x;
        int y;
        double sigma;//sigma用于计算半径r=1.5*sigma
        int intensity;//intensity用于当两个 blob重叠度高时取intensity大的(梯度大)
    };
    
    /*****生成LOG卷积后的scale_space******/
    vector<Mat> creat_scale_space(Mat& im_in, vector<double>& sigma)
    {
        vector<Mat> scale_space;
        for (int i = 0; i < sigma.size(); i++)
        {
            int n = ceil(sigma[i] * 3) * 2 + 1;
            Mat LOG = create_LOG(n, sigma[i]);
            Mat dst;
            //为了使得response一致,我们对做卷积的图片要先乘上sigma^2,这一步叫做scale normalize
            filter2D(im_in.mul(sigma[i] * sigma[i]), dst, -1, LOG, Point(-1, -1));
            scale_space.push_back(dst);
        }
    
        return scale_space;
    }
    
    /*******检测所有可能的blob**********/
    vector<struct blob> detect_blobs(Mat& im_in, double thresh, vector<double> et, int padding = 10)
    {
        vector<struct blob> blobs;
        Mat addborder, norm;
        /*The function copies the source image into the middle of the destination image.
        The areas to the left, to the right, 
        above and below the copied source image will be filled with extrapolated pixels*/
    
        copyMakeBorder(im_in, addborder, padding, padding, padding, padding, 
            BORDER_CONSTANT, Scalar(255));
    
        normalize(addborder, norm, 1, 0, NORM_MINMAX, CV_64F);
    
        vector<Mat> all_ims = creat_scale_space(norm, et);
    
    
        for (int i = 0; i < et.size(); i++)
        {
            Mat grayscale, mx;
            normalize(all_ims[i], grayscale, 0, 255, NORM_MINMAX, CV_8U, Mat());
            Mat structedElement(3, 3, CV_8U, Scalar(1));
    
            dilate(grayscale, mx, structedElement);//默认就是3*3,第三个参数可省略
    
            grayscale = (grayscale == mx)&(all_ims[i]>thresh);//取大于threshold并且是周围最大  
    
            for (int j = 0; j < norm.rows; j++)
            {
                for (int k = 0; k < norm.cols; k++)
                {
                    if (grayscale.at<double>(j, k)>0)//是局部最大值点
                    {
                        struct blob b;
                        b.x = j - padding;
                        b.y = k - padding;
                        b.sigma = et[i];
                        b.intensity = all_ims[i].at<double>(j, k);
                        blobs.push_back(b);
                    }
                }
            }
    
        }
    
        return blobs;
    }
    
    /*****************删除重叠度大的blob********************/
    vector<struct blob> prune_blobs(vector<struct blob>blobs_in)
    {
        vector<bool> keep(blobs_in.size(), true);
    
        for (int i = 0; i < blobs_in.size(); i++)
        {
            for (int j = 0; j < blobs_in.size(); j++)
            {
                if ((i == j) || (keep[i] == false) || (keep[j] == false))//??????????
                    continue;
    
                struct blob blobi = blobs_in[i];
                struct blob blobj = blobs_in[j];
    
                int xi = blobi.x;
                int yi = blobi.y;
                double ri = blobi.sigma;
    
                int xj = blobj.x;
                int yj = blobj.y;
                double rj = blobj.sigma;
                //算重叠度
                double d = sqrt((xj - xi)*(xj - xi) + (yj - yi)*(yj - yi));
                double rirj = ri + rj;
                double overlap_percent = rirj / d;
    
                if (overlap_percent > 2.0)
                {
                    if (blobi.intensity > blobj.intensity)
                    {
                        keep[i] = true;
                        keep[j] = false;
                    }
                    else {
                        keep[i] = false;
                        keep[j] = true;
                    }
                }
            }
        }
    
        vector<struct blob> blobs_out;
        for (int i = 0; i < blobs_in.size(); i++)
        if (keep[i])
            blobs_out.push_back(blobs_in[i]);
    
        return blobs_out;
    }
    int main()
    {
        Mat src, gray;
        src = imread("1.jpg");
        cvtColor(src, gray, CV_RGB2GRAY);
        vector<double> sigma = create_sigma(1.0, 0.2, 3.0);
        vector<struct blob> blobs = detect_blobs(gray, 0.2, sigma);
        vector<struct blob> blobs_trimmed = prune_blobs(blobs);
    
        for (int i = 0; i < blobs_trimmed.size(); i++)
        {
            struct blob b = blobs_trimmed[i];
            circle(src, Point(b.y, b.x), 1.5*b.sigma, Scalar(0), 2, 8, 0);
        }
    
        namedWindow("result", 1);
        imshow("result", src);
    
        waitKey(0);
        return 0;
    }
    View Code
  • 相关阅读:
    .net软件反编译笔记
    Asp.Net 网站一键部署技术(上)
    C# TreeGridView 实现进程列表
    HeidiSQL Navicat
    Flask项目中邮箱模块的应用
    如何在已有的Flask项目添加数据表结构?
    把u盘刻录成系统盘
    Object '<Tbl_next_week_change_state at 0x7f2c78d849e8>' is already attached to session '4' (this is '6')
    OSError: [Errno 98] Address already in use
    Linux下设置和查看环境变量
  • 原文地址:https://www.cnblogs.com/573177885qq/p/4731683.html
Copyright © 2020-2023  润新知