斑点检测
检测
2023-09-14 08:57:33 时间
参考: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; }
相关文章
- 细胞活力检测方法大盘点,CTG 法放大招?- MedChemExpress
- 快乐学AI系列——计算机视觉(3)目标检测
- Java检测对象是否相等详解编程语言
- 利用 Redis 检测记录过期情况(redis判断是否过期)
- 南京确诊病例中有宿管阿姨和兼职培训老师:已开展全员核酸检测
- 剑桥大学研发出可以快速检测水质的触摸屏
- 检测Linux服务器端口开启状态(linux端口是否开启)
- 检测Linux系统下的异常流量检测(linux异常流量)
- Linux系统漏洞检测:保护网络安全(linux漏洞检测)
- 雅虎开源色情图片检测神经网络
- Linux磁盘检测:提升系统性能的不二之选(linux磁盘检测)
- MySQL中c语言实现检测超时(c mysql 检测超时)
- 正常检测Redis连接情况有无异常(查看redis是否链接)
- js实现网页检测是否安装了FlashPlayer插件
- 使用JavaScript检测Firefox浏览器是否启用了Firebug的代码