图像中目标or内容疏密程度判断

比较简单,已基本满足我的需求。留了两个参数可调,根据不同需求来调节,我的是调的20,0.51就够了。测试了几百张图OK。

/*
 * sparseDense.h
 *	实验开始,第一次人工停止对焦的图片,判断样液浓度是否不符合要求
 *	是否太密,太密软件会报警要求稀释样液。
 *  Created on: 2019年10月10日
 *      Author: root wangdan
 *      version:V1.0.0
 */

#ifndef SRC_SPARSEDENSE_H_
#define SRC_SPARSEDENSE_H_

#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace cv;

class sparseDense {
public:
	sparseDense();
	virtual ~sparseDense();

	/*input:inputbgra--输入图像,人工“停止对焦”那一刻的图像
	 * 		windowsize-局部距离值的窗口,越小,疏密判断越准确,但不能太小,建议20
	 * 		thresh-----太密的局部区域占所有局部区域的比,大于此值报警太密,建议0.55
	 *output:-1--------输入图像有问题,空图
	 *		  0--------浓度符合要求(不密)。
	 *		  1--------浓度过密,软件报警。
	 * */
	int calculateSparseDense(unsigned char *image_pointer,int windowsize,double &thresh);

private:
	int imgrows;
	int imgcols;
	Mat inputbwimg;

	int lastrows;
	int lastcols;

	//距离图每20x20计算一个最频繁的距离值,局部距离值的窗口
	//越小,疏密判断越准确,但不能太小,>=10;建议=20
	int winsize;
	//winsizexwinsize窗口内,最频繁的距离值>distanthresh,那么此窗口不密;否则过密
	//越大表示希望仪器希望接受的程度偏稀;越小表示仪器希望接受更密程度 distanthresh=winsize
	int distanthresh;

	int fillholeCalcDistance(vector<int> &maxvalues);
};

#endif /* SRC_SPARSEDENSE_H_ */
#include "sparseDense.h"

sparseDense::sparseDense() {
	// TODO Auto-generated constructor stub
	imgrows=2048;
	imgcols=2448;
//	Mat inputbwimg;

	lastrows=imgrows/4;
	lastcols=imgcols/4;

	winsize=20;
	distanthresh=winsize;
}


int sparseDense::calculateSparseDense(unsigned char *image_pointer,int windowsize,double &thresh)
{
	winsize=windowsize;
	distanthresh=windowsize;

	if(image_pointer==NULL)
	{
		return -1;
	}

	Mat inputbgra(imgrows,imgcols,CV_8UC4);
	size_t primary_size_=imgrows*imgcols*4*sizeof(uchar);
	memcpy(inputbgra.data,image_pointer,primary_size_);

	Mat inputgray,inputbw;
	cv::cvtColor(inputbgra,inputgray,CV_BGRA2GRAY);
	cv::threshold(inputgray,inputbw,120,255,THRESH_BINARY_INV);

	cv::Size lastsize;
	lastsize.height=lastrows;
	lastsize.width=lastcols;
	resize(inputbw, inputbwimg, lastsize);

	vector<int> maxsvalues;
	fillholeCalcDistance(maxsvalues);
	int satisfynumber=0;
	int localmax=maxsvalues.size();
	for(int idx=0;idx!=localmax;idx++)
	{
		satisfynumber+=maxsvalues[idx];
	}
	double ratio=double(satisfynumber)/localmax;
	//cout<<"ratio is: "<<ratio<<endl;
	if(ratio>thresh)
	{
		return 1;//太密,报警
	}

	return 0;
}


int sparseDense::fillholeCalcDistance(vector<int> &maxvalues)
{
	std::vector<std::vector<cv::Point> > contours;
	std::vector<Vec4i> hierarchy;
	findContours(inputbwimg, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);

	Mat bwlast=Mat::zeros(lastrows,lastcols,CV_8UC1);
	for (int idx = 0; idx != (int)contours.size(); idx++)
	{
		drawContours(bwlast, contours, idx, Scalar(255), CV_FILLED);
	}
	//imwrite("bw.jpg",bwlast);
	cv::bitwise_not(bwlast,inputbwimg);
	//imwrite("bwnot.jpg",inputbwimg);

    Mat distance;
    distanceTransform(inputbwimg, distance, CV_DIST_L2, 3);


    //距离图每25x25计算一个局部最大值,图像共有N个局部最大值
    int maxsidxr=1;
    while(maxsidxr*winsize<lastrows)
    {
    	int maxsidxc=1;
		while(maxsidxc*winsize<lastcols)
		{
			//统计当前局部方块的距离值
			int numlocal=winsize*winsize;
			int localdistance[numlocal]={0};
			for(int r=(maxsidxr-1)*winsize;r!=maxsidxr*winsize;r++)
			{
				for(int c=(maxsidxc-1)*winsize;c!=maxsidxc*winsize;c++)
				{
					int current=int(distance.ptr<float>(r)[c]);
					if(current>0 && current<numlocal)
					{
						localdistance[current]+=1;
					}
				}
			}
			//当前局部方块距离值主要集中在哪个区间
			int maxdistsum=0,maxdist=0;
			for(int idx=0;idx!=numlocal;idx++)
			{
				if(localdistance[idx]>maxdistsum)
				{
					maxdistsum=localdistance[idx];
					maxdist=idx;
				}
			}
			//当前局部最大值计算完毕
			//cout<<maxdist<<" ";
			//当前局部最大值如果大于阈值,证明此局部是比规定浓度还稀,符合要求;
			//否则,此局部比规定浓度密,不符合要求;
			int isdense=0;
			int notsparse=1;
			if(maxdist<distanthresh)
			{
				maxvalues.push_back(notsparse);
			}
			else
			{
				maxvalues.push_back(isdense);
			}

			//移到此行下一列方块
			maxsidxc++;
		}
		//cout<<endl;
		//列所有局部最大值计算完毕
    	maxsidxr++;
    }
    //行所有局部最大值计算完毕

	return 0;
}


sparseDense::~sparseDense() {
	// TODO Auto-generated destructor stub
}

测试了几百张图片,各种形状各种大小的目标的图像,发现判断还比较准确。

但是有一个前提,图像中的目标一定要比较均匀,不能图像的左下角密密麻麻而另外四分之三图像都没目标,这种极度不均匀的情况是不行的,不能作为输入图像。因为我们判断一个试管中样液是否浓或稀,一定要摇晃均匀才看整体浓或稀。反正就是目标可以有不同形状不同大小,但输入图像不能极度不均匀。输入图像整体越均匀,那么算法判断越准确。

  小不点的美图。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

元气少女缘结神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值