精华内容
下载资源
问答
  • set按长度分割
    千次阅读
    2017-11-03 15:16:09

    我们在使用java中的集合(Collection、List、Set等)的时候,可能因为某种限制需要将大集合按照固定的长度拆分为N个小的集合。

    如:有一个List<String> list 里面有1099个原始,我需要按照固定长度50,来拆分这个集合为很多小集合,每个集合的原始是50个元素,可能最后一个小集合的长度不到50.

    如何做呢?网上有不少资料,代码如下:

     

        /**
         * 拆分集合
         * 
         * @param <T> 泛型对象
         * @param resList 需要拆分的集合
         * @param subListLength 每个子集合的元素个数
         * @return 返回拆分后的各个集合组成的列表
         * 代码里面用到了guava和common的结合工具类
         **/
        public static <T> List<List<T>> split(List<T> resList, int subListLength) {
            if (CollectionUtils.isEmpty(resList) || subListLength <= 0) {
                return Lists.newArrayList();
            }
            List<List<T>> ret = Lists.newArrayList();
            int size = resList.size();
            if (size <= subListLength) {
                // 数据量不足 subListLength 指定的大小
                ret.add(resList);
            } else {
                int pre = size / subListLength;
                int last = size % subListLength;
                // 前面pre个集合,每个大小都是 subListLength 个元素
                for (int i = 0; i < pre; i++) {
                    List<T> itemList = Lists.newArrayList();
                    for (int j = 0; j < subListLength; j++) {
                        itemList.add(resList.get(i * subListLength + j));
                    }
                    ret.add(itemList);
                }
                // last的进行处理
                if (last > 0) {
                    List<T> itemList = Lists.newArrayList();
                    for (int i = 0; i < last; i++) {
                        itemList.add(resList.get(pre * subListLength + i));
                    }
                    ret.add(itemList);
                }
            }
            return ret;
        }
    
    // 运行代码
    public static void main(String[] args) {
        List<String> list = Lists.newArrayList();
        int size = 1099;
        for (int i = 0; i < size; i++) {
            list.add("hello-" + i);
        }
    
        List<List<String>> temps = split(list, 6);
        int j = 0;
        for (List<String> obj : temps) {
            System.out.println(String.format("row:%s -> size:%s,data:%s", ++j, obj.size(), obj));
        }
    }

      其实我平日用的更多的是guava框架,它自带了一个方法可以实现上面的集合切割的功能。代码如下:

     

    public static void main(String[] args) {
        List<String> list = Lists.newArrayList();
        int size = 1099;
        for (int i = 0; i < size; i++) {
            list.add("hello-" + i);
        }
        // 切割大集合到指定的长度:11
        List<List<String>> rsList = Lists.partition(list, 11);
        int i = 0;
        for (List<String> obj : rsList) {
            System.out.println(String.format("row:%s -> size:%s,data:%s", ++i, obj.size(), obj));
        }
    }

     推荐大家使用guava的功能,它们都是经过严格的单元测试的代码。

    更多相关内容
  • 水平集LevelSet 分割图像

    千次阅读 2021-02-26 18:15:31
    1、水平集的是一个很好的分割算法,其使用比较多的是医学图像领域。其有一些有点也有一些缺点 其会计算图片的前景灰度、背景灰度。前景是灰度值大的目标,如果前景目标太小,则会导致其分割的不...levelset.hpp #i

    1、水平集的是一个很好的分割算法,其使用比较多的是医学图像领域。其有一些有点也有一些缺点

    其会计算图片的前景灰度、背景灰度。前景是灰度值大的目标,如果前景目标太小,则会导致其分割的不准确。其算法原理跟大津算法类似。其分割可以补偿一点缺失的边缘,这个特性很适合医学图像领域,因为医学图像很多噪点,边缘不明确的现象,还有一个优点是分割速度快。下面是一些例子:

    分割成功并补偿了缺失边缘的:

    分割失败:

    灯光条太小,其分割成的是整张图

    下面是水平集的原代码:

    levelset.hpp

    #include <vector>  
    #include <opencv2/opencv.hpp> 
    using namespace cv;
    using namespace std;
     
     
     
    class LevelSet
    {
    public:
    	LevelSet();
    	~LevelSet();
     
    	//基本参数  
    	int m_iterNum;      //迭代次数  
    	float m_lambda1;    //全局项系数  
    	float m_nu;     //长度约束系数ν  
    	float m_mu;     //惩罚项系数μ  
    	float m_timestep;   //演化步长δt  
    	float m_epsilon;    //规则化参数ε  
     
    	//过程数据  
    	Mat m_mImage;       //源图像  
     
    	int m_iCol;     //图像宽度  
    	int m_iRow;     //图像高度  
    	int m_depth;        //水平集数据深度  
    	float m_FGValue;    //前景值  
    	float m_BKValue;    //背景值  
     
    	//初始化水平集  
    	void initializePhi(Mat img,  //输入图像  
    		int iterNum, //迭代次数  
    		Rect boxPhi);//前景区域  
    	void EVolution();   //演化  
     
    	Mat m_mPhi;     //水平集:φ  
    protected:
    	Mat m_mDirac;       //狄拉克处理后水平集:δ(φ)  
    	Mat m_mHeaviside;   //海氏函数处理后水平集:Н(φ)  
    	Mat m_mCurv;        //水平集曲率κ=div(▽φ/|▽φ|)  
    	Mat m_mK;       //惩罚项卷积核  
    	Mat m_mPenalize;    //惩罚项中的▽<sup>2</sup>φ  
     
    	void Dirac();       //狄拉克函数  
    	void Heaviside();   //海氏函数  
    	void Curvature();   //曲率  
    	void BinaryFit();   //计算前景与背景值  
    };
    

    levelset.cpp

     

    #include<iostream>
    #include<opencv.hpp>
    #include"levelset.hpp"
    using namespace std;
    using namespace cv;
     
     
    LevelSet::LevelSet()
    {
    	m_iterNum = 300;
    	m_lambda1 = 1;
    	m_nu = 0.001 * 255 * 255;
    	m_mu = 1.0;
    	m_timestep = 0.1;
    	m_epsilon = 1.0;
    }
     
     
    LevelSet::~LevelSet()
    {
    }
     
    void LevelSet::initializePhi(Mat img, int iterNum, Rect boxPhi)
    {
    	//boxPhi是前景区域  
    	m_iterNum = iterNum;
    	cvtColor(img, m_mImage, CV_BGR2GRAY);
     
    	m_iCol = img.cols;
    	m_iRow = img.rows;
    	m_depth = CV_32FC1;
     
    	//显式分配内存  
    	m_mPhi = Mat::zeros(m_iRow, m_iCol, m_depth);
    	m_mDirac = Mat::zeros(m_iRow, m_iCol, m_depth);
    	m_mHeaviside = Mat::zeros(m_iRow, m_iCol, m_depth);
     
    	//初始化惩罚性卷积核  
    	m_mK = (Mat_<float>(3, 3) << 0.5, 1, 0.5,
    		1, -6, 1,
    		0.5, 1, 0.5);
     
    	int c = 2;
    	for (int i = 0; i < m_iRow; i++)
    	{
    		for (int j = 0; j < m_iCol; j++)
    		{
    			if (i<boxPhi.y || i>boxPhi.y + boxPhi.height || j<boxPhi.x || j>boxPhi.x + boxPhi.width)
    			{
    				m_mPhi.at<float>(i, j) = -c;
    			}
    			else
    			{
    				m_mPhi.at<float>(i, j) = c;
    			}
    		}
    	}
    }
     
    void LevelSet::Dirac()
    {
    	//狄拉克函数  
    	float k1 = m_epsilon / CV_PI;
    	float k2 = m_epsilon*m_epsilon;
    	for (int i = 0; i < m_iRow; i++)
    	{
    		float *prtDirac = &(m_mDirac.at<float>(i, 0));
    		float *prtPhi = &(m_mPhi.at<float>(i, 0));
     
    		for (int j = 0; j < m_iCol; j++)
    		{
    			float *prtPhi = &(m_mPhi.at<float>(i, 0));
    			prtDirac[j] = k1 / (k2 + prtPhi[j] * prtPhi[j]);
    		}
    	}
    }
     
    void LevelSet::Heaviside()
    {
    	//海氏函数  
    	float k3 = 2 / CV_PI;
    	for (int i = 0; i < m_iRow; i++)
    	{
    		float *prtHeaviside = (float *)m_mHeaviside.ptr(i);
    		float *prtPhi = (float *)m_mPhi.ptr(i);
     
    		for (int j = 0; j < m_iCol; j++)
    		{
    			prtHeaviside[j] = 0.5 * (1 + k3 * atan(prtPhi[j] / m_epsilon));
    		}
    	}
    }
     
    void LevelSet::Curvature()
    {
    	//计算曲率  
    	Mat dx, dy;
    	Sobel(m_mPhi, dx, m_mPhi.depth(), 1, 0, 1);
    	Sobel(m_mPhi, dy, m_mPhi.depth(), 0, 1, 1);
     
    	for (int i = 0; i < m_iRow; i++)
    	{
    		float *prtdx = (float *)dx.ptr(i);
    		float *prtdy = (float *)dy.ptr(i);
    		for (int j = 0; j < m_iCol; j++)
    		{
    			float val = sqrtf(prtdx[j] * prtdx[j] + prtdy[j] * prtdy[j] + 1e-10);
    			prtdx[j] = prtdx[j] / val;
    			prtdy[j] = prtdy[j] / val;
    		}
    	}
    	Mat ddx, ddy;
    	Sobel(dx, ddy, m_mPhi.depth(), 0, 1, 1);
    	Sobel(dy, ddx, m_mPhi.depth(), 1, 0, 1);
    	m_mCurv = ddx + ddy;
    }
     
    void LevelSet::BinaryFit()
    {
    	//先计算海氏函数  
    	Heaviside();
     
    	//计算前景与背景灰度均值  
    	float sumFG = 0;
    	float sumBK = 0;
    	float sumH = 0;
    	//float sumFH = 0;  
    	Mat temp = m_mHeaviside;
    	Mat temp2 = m_mImage;
    	float fHeaviside;
    	float fFHeaviside;
    	float fImgValue;
    	for (int i = 1; i < m_iRow; i++)
    	{
    		float *prtHeaviside = &(m_mHeaviside.at<float>(i, 0));
    		uchar *prtImgValue = &(m_mImage.at<uchar>(i, 0));
    		for (int j = 1; j < m_iCol; j++)
    		{
    			fImgValue = prtImgValue[j];
    			fHeaviside = prtHeaviside[j];
    			fFHeaviside = 1 - fHeaviside;
     
    			sumFG += fImgValue*fHeaviside;
    			sumBK += fImgValue*fFHeaviside;
    			sumH += fHeaviside;
    		}
    	}
    	m_FGValue = sumFG / (sumH + 1e-10);         //前景灰度均值  
    	m_BKValue = sumBK / (m_iRow*m_iCol - sumH + 1e-10); //背景灰度均值  
    }
    Mat showIMG;
    void LevelSet::EVolution()
    {
    	float fCurv;
    	float fDirac;
    	float fPenalize;
    	float fImgValue;
     
    	for (int i = 0; i < m_iterNum; i++)
    	{
    		Dirac();
    		Curvature();
    		BinaryFit();
    		filter2D(m_mPhi, m_mPenalize, m_depth, m_mK, Point(1, 1));//惩罚项的△φ  
    		for (int i = 0; i < m_iRow; i++)
    		{
    			float *prtCurv = &(m_mCurv.at<float>(i, 0));
    			float *prtDirac = &(m_mDirac.at<float>(i, 0));
    			float *prtPenalize = &(m_mPenalize.at<float>(i, 0));
    			uchar *prtImgValue = &(m_mImage.at<uchar>(i, 0));
    			for (int j = 0; j < m_iCol; j++)
    			{
    				fCurv = prtCurv[j];
    				fDirac = prtDirac[j];
    				fPenalize = prtPenalize[j];
    				fImgValue = prtImgValue[j];
     
    				float lengthTerm = m_nu* fDirac * fCurv;                    //长度约束  
    				float penalizeTerm = m_mu*(fPenalize - fCurv);                  //惩罚项  
    				float areaTerm = fDirac * m_lambda1 *                       //全局项  
    					(-((fImgValue - m_FGValue)*(fImgValue - m_FGValue))
    					+ ((fImgValue - m_BKValue)*(fImgValue - m_BKValue)));
     
    				m_mPhi.at<float>(i, j) = m_mPhi.at<float>(i, j) + m_timestep*(lengthTerm + penalizeTerm + areaTerm);
    			}
    		}
     
    		//显示每一次演化的结果  
     
     
    		//return showIMG;
    	}
    	cvtColor(m_mImage, showIMG, CV_GRAY2BGR);
    	Mat Mask = m_mPhi >= 0;   //findContours的输入是二值图像  
    	dilate(Mask, Mask, Mat(), Point(-1, -1), 3);
    	erode(Mask, Mask, Mat(), Point(-1, -1), 3);
    	vector<vector<Point> > contours;
    	findContours(Mask,
    		contours,// 轮廓点  
    		RETR_EXTERNAL,// 只检测外轮廓  
    		CHAIN_APPROX_NONE);// 提取轮廓所有点  
    	drawContours(showIMG, contours, -1, Scalar(255, 0, 0), 2);
    	namedWindow("Level Set后图像");
    	imshow("Level Set后图像", showIMG);
    	waitKey(1);
    }
    void main()
    {
    	Mat img = imread("0.jpg");
    	imshow("原图", img);
    	LevelSet ls;
    	VideoCapture cap;
    	cap.open(0);
    	cap.set(CV_CAP_PROP_FRAME_WIDTH, 2048);
    	cap.set(CV_CAP_PROP_FRAME_HEIGHT, 1536);
    	for (;;)
    	{
    		cap >> img;
    		resize(img, img, Size(img.cols / 8, img.rows / 8));
    		imshow("原图", img);
    		Rect rec(0, 0, img.cols, img.rows);
    		ls.initializePhi(img, 30, rec);
    		ls.EVolution();
    	}
    	//imshow("Level Set后图像", showIMG);
    	waitKey(0);
    }
    

     

    展开全文
  • 基于level set(水平集方法)导的图像分割。区别于传统active contour活动轮廓,主要是根据图像的强度,利用数学方法进行迭代。

    1. 传统依赖边界的active contour 算法

    传统的levelset方法依赖于图像边界的梯度,需要引入一个单调递减函数edge-detector g ( z ) g(z) g(z)定义levelset方法的迭代速度。
    s t : lim ⁡ z → ∞ g ( z ) = 0 st: \lim\limits_{z\rarr \infty} g(z) = 0 st:zlimg(z)=0

    例如: g ( ∇ u 0 ( x , y ) ) = 1 1 + ∣ ∇ G σ ∗ u 0 ( x , y ) ∣ p g(\nabla u_0(x, y)) = \frac{1}{1 + |\nabla G_{\sigma}*u_0(x, y)|^p} g(u0(x,y))=1+Gσu0(x,y)p1
    u 0 ( x , y ) = z u_0(x, y) = z u0(x,y)=z
    原图像看作曲面 Σ ( x , y , u 0 ( x , y ) ) = 0 \Sigma(x, y, u_0(x, y)) = 0 Σ(x,y,u0(x,y))=0

    level set方法定义了一系列等高线
    ϕ ( x , y ) = c i \phi(x, y) = c_i ϕ(x,y)=ci
    我们不妨用曲线 C C C: ϕ ( x , y ) = 0 \phi(x, y) = 0 ϕ(x,y)=0作为初始曲线,在根据需要对进行迭代
    此时曲线 C t i C_{t_{i}} Cti : ϕ ( t i , x , y ) = 0 \phi(t_i, x, y) = 0 ϕ(ti,x,y)=0在迭代的过程中不断向图像的边界逼近,最后稳定下来即得到边界。

    Remark: ϕ ( t , x , y ) \phi(t, x, y) ϕ(t,x,y)其中 ϕ ( 0 , x , y ) = ϕ 0 ( x , y ) \phi(0, x, y) = \phi_0(x, y) ϕ(0,x,y)=ϕ0(x,y),根据定义的 ∂ ϕ ∂ t = V ∣ ∇ ϕ ∣ \frac{\partial\phi}{\partial t} = V |\nabla\phi| tϕ=Vϕ利用迭代法求解PDE

    level set方法有以下结论:
    单位切向量 T T T, n = − ∇ ϕ ∣ ∇ ϕ ∣ n = -\frac{\nabla\phi}{|\nabla\phi|} n=ϕϕ , ϕ ( x , y ) = c \phi(x, y) = c ϕ(x,y)=c确定曲线 C ( x , y ) C(x, y) C(x,y)

    1. n ⊥ T n \perp T nT
      证明:由IFT(隐函数定理)
      ϕ ( x , y ) − c = 0 \phi(x, y) - c = 0 ϕ(x,y)c=0 ∣ ∇ ϕ ∣ ≠ 0 |\nabla\phi| \neq 0 ϕ=0的邻域内唯一确定了 y = y ( x ) y = y(x) y=y(x)
      st: ϕ ( x , y ( x ) ) − c = 0 \phi(x, y(x)) - c = 0 ϕ(x,y(x))c=0
      ∴ ϕ x + d y d x ϕ y = 0 \therefore \phi_x + \frac{dy}{dx}\phi_y = 0 ϕx+dxdyϕy=0
      n ⋅ T = c o s n t ∗ ( 1 ,   d y d x ) ⋅ ( ϕ x ,   ϕ y ) = c o n s t ∗ ( ϕ x + d y d x ϕ y ) = 0 □ n \cdot T = cosnt * (1,\space\frac{dy}{dx})\cdot (\phi_x, \space\phi_y) \\= const * (\phi_x + \frac{dy}{dx}\phi_y ) = 0 \quad \square nT=cosnt(1, dxdy)(ϕx, ϕy)=const(ϕx+dxdyϕy)=0
    2. d i v ( ∇ ϕ ∣ ∇ ϕ ∣ ) = κ div(\frac{\nabla\phi}{|\nabla\phi|}) = \kappa div(ϕϕ)=κ
      (利用 ϕ s s = 0 \phi_{ss} = 0 ϕss=0在level set上 ϕ \phi ϕ是常数)证明。
    3. ∂ C ∂ t = V n    ⟺    ∂ ϕ ∂ t = V ∣ ∇ ϕ ∣ , V \frac{\partial C}{\partial t} = Vn \iff \frac{\partial \phi}{\partial t} = V|\nabla \phi|, V tC=Vntϕ=VϕV是常数
      (直接利用链式求导法则,证明略)

    方便起见在此只举一个例子:
    Geometric active contour model
    { ∂ ϕ ∂ t = g ( ∣ ∇ u 0 ∣ ) ∣ ∇ ϕ ∣ ( d i v ( ∇ ϕ ∣ ∇ ϕ ∣ ) + v ) ϕ ( 0 , x , y ) = ϕ 0 ( x , y ) \begin{cases}\frac{\partial\phi}{\partial t} = g(|\nabla u_0|)|\nabla \phi|(div(\frac{\nabla\phi}{|\nabla \phi|})+v)\\\phi(0, x, y) = \phi_0(x, y)\end{cases} {tϕ=g(u0)ϕ(div(ϕϕ)+v)ϕ(0,x,y)=ϕ0(x,y)
    式中 ∂ ϕ ∂ t \frac{\partial\phi}{\partial t} tϕ为图像迭代的速度, d i v ( ∇ ϕ ∣ ∇ ϕ ∣ ) div(\frac{\nabla\phi}{|\nabla \phi|}) div(ϕϕ)是对曲线C曲率 κ \kappa κ的模拟, v是常数修正项(感性地理解:在曲率越大的地方,边界收缩的“张力“越强)。由于 ∇ ϕ \nabla\phi ϕ在边界处 g ( ∇ u 0 ( x , y ) ) g(\nabla u_0(x, y)) g(u0(x,y))很小,控制迭代速度缓慢,此时曲线 ϕ \phi ϕ近似原图像的边界。

    此外还有测地线模型等,都依赖于图像边界的梯度进行迭代,不一一举例。
    缺点:由于在现实中 g g g不会趋于0,即使达到边界仍然会继续迭代。
    如果原图像噪声较多则需要很强的gauss模糊化处理。

    2. 不标题依赖边界的方法

    本质上也是一个最小化能量的method。
    优点:不依赖初始曲线的选取和图像边界的梯度
    曲线 C C C所围成的区域 ω \omega ω
    定义了 F ( c 1 , c 2 , C ) = μ L e n g t h ( C ) + v A r e a ( ω ) + λ 1 ∫ ω ∥ u ( x , y ) − c 1 ∥ 2 d x d y + λ 2 ∫ Ω − ω ∥ u ( x , y ) − c 2 ∥ 2 F(c1, c2, C) = \mu Length(C) + vArea(\omega) + \lambda_1 \int_{\omega} \Vert u(x, y) - c_1 \Vert^2 dxdy + \lambda_2\int_{\Omega - \omega} \Vert u(x, y) - c_2 \Vert^2 F(c1,c2,C)=μLength(C)+vArea(ω)+λ1ωu(x,y)c12dxdy+λ2Ωωu(x,y)c22c1,c2分别是在 w w w内外 u ( x , y ) u(x, y) u(x,y)的平均值。当C为边界时,后两项趋于最小

    前两项是对曲线长度所围成的面积的限制。
    在此基础上引入level set方法,
    则以上各项均可用广义函数:单位越阶函数H以及Dirac函数结合原图像和曲线 ϕ \phi ϕ表示。
    ω = { ( x , y ) ∈ Ω ,   ϕ ( x , y ) > 0 } \omega = \{(x, y) \isin \Omega,\space \phi(x, y) > 0\} ω={(x,y)Ω, ϕ(x,y)>0}
    ∴   A r e a ( ω ) = ∫ Ω H ( ϕ ( x , y ) ) d x d y \therefore\space Area(\omega) = \int_{\Omega} H(\phi(x, y))dxdy  Area(ω)=ΩH(ϕ(x,y))dxdy
    L e n g t h ( C ) = ∫ Ω ∇ H ( ϕ ( x , y ) ) d x d y = ∫ Ω δ ( ϕ ( x , y ) ) ∇ ϕ ( x , y ) d x d y Length(C) = \int_{\Omega} \nabla H(\phi(x, y))dxdy \\ = \int_{\Omega}\delta(\phi(x, y)) \nabla\phi(x, y)dxdy Length(C)=ΩH(ϕ(x,y))dxdy=Ωδ(ϕ(x,y))ϕ(x,y)dxdy
    c1, c2类似,不在此赘述。
    于是得到:

    问题转化为求 ϕ ( x , y ) \phi(x, y) ϕ(x,y)使得上述能量项最小。此时的 ϕ ( x , y ) = 0 \phi(x, y) = 0 ϕ(x,y)=0所决定的曲线即为边界。
    对regularized的泛函 F ϵ ( c 1 , c 2 , ϕ ) F_{\epsilon}(c1, c2, \phi) Fϵ(c1,c2,ϕ),将c1, c2看作常数,即可写出其Elur-Lagrange方程,得到局部极小值的必要条件:
    ∂ ϕ ∂ t = δ ϵ ( ϕ ) [ μ ⋅ d i v ( ∇ ϕ ∣ ∇ ϕ ∣ ) − v − λ 1 ( u − c 1 ) 2 + λ 2 ( u − c 2 ) 2 ] = 0 \frac{\partial\phi}{\partial t} = \delta_{\epsilon}(\phi)[\mu \cdot div(\frac{\nabla\phi}{|\nabla\phi|}) - v - \lambda_1(u - c_1)^2 + \lambda_2(u - c_2)^2] = 0 tϕ=δϵ(ϕ)[μdiv(ϕϕ)vλ1(uc1)2+λ2(uc2)2]=0
    问题再次转化为解上述PDE
    可利用迭代方法求解。

    对于H的不同的近似得到了不同的能量的表达式。其中有参数 ϵ \epsilon ϵ
    δ ϵ = H ϵ ˙ \delta_{\epsilon} = \dot{H_{\epsilon}} δϵ=Hϵ˙, s t : ϵ → 0 ,   H ϵ → H st: \epsilon \rarr 0,\space H_{\epsilon} \rarr H st:ϵ0, HϵH
    对于不同 H ϵ H_{\epsilon} Hϵ的选取会对最后结果全局性、局部性等造成不同影响。
    文中提供了两种近似:

    上图分别是两函数以及其导函数的图像。由于 H 1 , ϵ H_{1, \epsilon} H1,ϵ在超过 ϵ \epsilon ϵ时恒等于0,而E-L方程规定的是函数的局部行为,采用前者更易陷在局部最小值。

    3. 具体实现

    代码的实现与论文有两处不同
    另外在更新公式中,后两项internal需要归一化。这个值在计算过程中往往过大(会达到数百),使得迭代速度过快,不能达到稳定结果,如下图。

    ϕ \phi ϕ 的迭代计算中,如果只更新曲线附近的 ϕ \phi ϕ会带来比较好的效果,否则会使得整张图片的 ϕ \phi ϕ值都为0。

    图片描述

    在这里插入图片描述
    左图是边界,右图是 ϕ \phi ϕ

    4. 代码

    import numpy as np
    import matplotlib.pyplot as plt
    from PIL import Image
    
    
    def init_circle(size, x0, y0, radius):
        col, row = size
        phi = np.zeros(shape=(row, col), dtype=float)
        for i in range(row):
            for j in range(col):
                phi[i, j] = -np.sqrt((i - x0)**2 + (j - y0)**2) + radius
        return phi
    
    
    def H_epsilon(z, epsilon):
        return 0.5 * (1 + 2 / np.pi * (np.arctan(z / epsilon)))
    
    
    def delta_epsilon(z, epsilon):
        return (epsilon / np.pi) / (epsilon ** 2 + z ** 2)
    
    
    def iterate(image, phi0, mu = 0, v = 0, lmb1=1, lmb2=1, epsilon=1, steps=100, rate=0.1):
        array_image = np.array(image)
        phi = phi0
        fig, Axes = plt.subplots(ncols=2)
        show_curve_and_phi(fig, array_image, phi0)
    
        for step in range(steps):
            C = np.flatnonzero(np.logical_and(phi >= - 1, phi <= 1))
            show_curve_and_phi(fig, array_image, phi)
    
            H = H_epsilon(phi, epsilon)
            delta = delta_epsilon(phi, epsilon)
    
            inside_idx = np.flatnonzero(phi >= 0)
            outside_idx = np.flatnonzero(phi < 0)
    
            c1 = np.sum(array_image.flat[inside_idx]) / (len(inside_idx) + 1e-10)
            c2 = np.sum(array_image.flat[outside_idx]) / (len(outside_idx) + 1e-10)
    
            constrain = mu * formulate(phi).flat[C] - v
            internal = -lmb1 * (array_image.flat[C] - c1) ** 2 + lmb2 * (array_image.flat[C] - c2) ** 2
    
            D = delta.flat[C] * (constrain + internal / np.max(internal))
            phi.flat[C] = rate * D
    
    def gradient(f):
        fx = f
        fy = f
        n, m = f.shape
        fx[:, 0] = f[:, 1] - f[:, 0]
        fx[:, -1] = f[:, -1] - f[:, -2]
        fy[0, :] = f[1, :] - f[0, :]
        fy[-1, :] = f[-1, :] - f[-2, :]
        for j in range(1, m - 1):
            fx[:, j] = (f[:, j + 1] - f[:, j - 1]) / 2.0
        for i in range(1, n - 1):
            fy[i, :] = (f[i + 1, :] - f[i - 1, :]) / 2.0
        return fx, fy
    
    
    def formulate(phi):
        phi_x, phi_y = gradient(phi)
        norm_gradient = np.sqrt(phi_x ** 2 + phi_y ** 2 + 1e-10)
        nxx, _ = gradient(phi_x / norm_gradient)
        _, nyy = gradient(phi_y / norm_gradient)
        return nxx + nyy
    
    
    def show_curve_and_phi(fig, image, phi):
        fig.axes[0].cla()
        fig.axes[0].imshow(image, cmap='gray')
        fig.axes[0].contour(phi, 0, colors='red')
        fig.axes[0].set_axis_off()
    
        fig.axes[1].cla()
        fig.axes[1].imshow(phi)
        fig.axes[1].set_axis_off()
    
        plt.pause(0.001)
    
    
    if __name__ == '__main__':
        image = Image.open("spiral.jpg").convert("L")
        plt.ion()
        [col, row] = image.size
        phi0 = init_circle(image.size, row / 2, col / 2, 50)
        iterate(image, phi0)
        
    
    展开全文
  • 找了网上很多资料,都没有详细的做法有的还很复杂,自己写了个分割函数,通过直接查询就能分割多行,很方便。
  • 传入的是一个时间段,并且时间长度有要求,所以这里对时间进行了一个分割,下面是算法: // 将时间按照星期分割 public List<String> doDateType(String startDate, String endDate) throws Pars

    首先谢谢这两个博客的分享
    Java 将一段时间以周、月、季分割
    Java将日期拆分成按周或月时间段统计
    然后这两个算法执行后的结果都有一些小的问题,或者可以说并不是我想要的结果,我要做的需求就是调用钉钉的接口,获取公司员工的打卡:
    在这里插入图片描述
    传入的是一个时间段,并且时间长度有要求,所以这里对时间进行了一个分割,下面是算法:

    	// 将时间按照星期分割
    	public List<String> doDateType(String startDate, String endDate) throws ParseException {
    		List<String> resultlist = new ArrayList<String>();
    		List<String> listWeekOrMonth = new ArrayList<String>();
    		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    		DateFormat olddateFormat = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
    		DateFormat newdateFormat = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
    		Date sDate = dateFormat.parse(startDate);
    		Calendar sCalendar = Calendar.getInstance();
    		sCalendar.setFirstDayOfWeek(Calendar.MONDAY);
    		sCalendar.setTime(sDate);
    		Date eDate = dateFormat.parse(endDate);
    		Calendar eCalendar = Calendar.getInstance();
    		eCalendar.setFirstDayOfWeek(Calendar.MONDAY);
    		eCalendar.setTime(eDate);
    		boolean bool = true;
    		while (sCalendar.getTime().getTime() < eCalendar.getTime().getTime()) {
    			int week1 = sCalendar.get(Calendar.DAY_OF_WEEK) - 1;// 周几
    			if (bool || week1 == 0 || week1 == 1) {
    				if (week1 == 0) {// 周日
    					sCalendar.set(Calendar.HOUR_OF_DAY, 23);
    					sCalendar.set(Calendar.MINUTE, 59);
    					sCalendar.set(Calendar.SECOND, 59);
    					String time = newdateFormat.format(sCalendar.getTime());
    					listWeekOrMonth.add(time);
    				} else {
    					sCalendar.set(Calendar.HOUR_OF_DAY, 0);
    					sCalendar.set(Calendar.MINUTE, 0);
    					sCalendar.set(Calendar.SECOND, 0);
    					String time = dateFormat.format(sCalendar.getTime());
    					listWeekOrMonth.add(time);
    				}
    				bool = false;
    			}
    			sCalendar.add(Calendar.DAY_OF_MONTH, 1);// 加一天
    		}
    		Calendar newCalendar = eCalendar;
    		listWeekOrMonth.add(olddateFormat.format(newCalendar.getTime()));
    		if (listWeekOrMonth.size() % 2 != 0) {
    			listWeekOrMonth.add(dateFormat.format(eCalendar.getTime()));
    		}
    		for (int g = 0; g < listWeekOrMonth.size(); g += 2) {
    			String startTime = listWeekOrMonth.get(g);
    			String endTime = listWeekOrMonth.get(g + 1);
    			String time = startTime + "@" + endTime;
    			resultlist.add(time);
    		}
    		return resultlist;
    	}
    
    展开全文
  • Hive中的explode()函数和collect_set()函数

    万次阅读 2017-12-01 09:49:56
    最近在Hive中查询测试数据用到explode()函数比较多,所以今天整理一下,方便以后查阅。...说明:返回字符串A从start位置开始,长度为len的字符串。这里需要注意的是初始位置是从1开始。 2.explode()函...
  • set @counter=@counter + 1 --分隔符的计数器 set @start=@location+@seed set @location=charindex(@split,@str,@start)  end  if len(@str) = 0 set @counter = 0  else set @counter = @counter + 1 ...
  • mysql分割字符串应该如何实现呢?...例如:update `edw_video` set company = substring(keyword,1,length(SUBSTRING_INDEX(keyword,",",1)))名称:SPLIT_SUB_STR1(取得split字符串的第一段)参数:st...
  • 与经典的CNN在卷积层之后使用全连接层得到固定长度的特征向量进行分类(全联接层+softmax输出)不同,FCN可以接受任意尺寸的输入图像,采用反卷积层对最后一个卷积层的feature map进行上采样, 使它恢复到输入图像...
  • 1. split 按照指定的字符分割,如按照";"或 "/"等分割 QString str = "hello,world" QStringList list = str.split(","); QString a = list[0]; //a = "hello" QString b = list[1]; //b = "world" QString str2 = ...
  • 【shell】shell字符串分割|文件分割

    千次阅读 2021-11-03 16:24:36
    一、字符串分割 1、awk分割 2、利用shell 中 变量 的字符串替换成空格分割 3、设置分隔符,通过 IFS 变量 4、利用tr 指令实现字符替换 二、文件分割 附录 【转】linux下awk内置函数的使用(split/substr/...
  • Oracle sqlplus的set命令详细使用和设置

    千次阅读 2019-09-24 18:19:48
    Oracle sqlplus的set命令详细使用和设置 SQL*Plus是Oracle提供的访问数据库服务器的...
  • 区域生长的基本方法是从被分割对象里作为种子区域 ( 通常是一个或多个像素 ) 的一个区域开始,在种子区域的相邻像素寻找与种子像素有相同或相似性质的像素,并将这些像素合并到种子像素所在的区域中。将这些新像素...
  • 数据集分割

    千次阅读 2020-10-07 11:27:31
    分割数据集并载入,注意要保证数据与标签一一对应 在训练和测试时使用分割后的数据 1. 载入数据(以Cifar10为例) 利用torchvision.datasets.CIFAR10直接载入数据,具体代码如下所示: train_path = '' #训练数据的
  • nettyserver 自定义数据分割

    千次阅读 2022-01-22 22:46:17
    自定义分割符号 Client&ZDBH01&87.11&0.00&0.00&46.577&-14.707&-72.513&108.91785&34.22269&end# package com.jeesite.modules.nettyServer; impor.
  • 代码见Github:mattzheng/U-Net-Demo ...来看几个变形: (1)Supervise.ly 公司。 在用 Faster-RCNN(基于 NasNet)定位 + UNet-like 架构的分割,来做他们数据众包图像分割方向的主动学习,当时没有使用 Mask...
  • 如上文“谈谈Mysql 字符串连接 CONCAT CONCAT_WS GROUP_CONCAT区别及使用场景”中提到的字符串连接函数,本文继续讲述Mysql剩余常用字符串函数的使用注意事项及使用场景:字符串长度char_length,length; 字符串查找...
  • 数字图像处理:实验六 图像分割

    千次阅读 2022-05-03 16:12:27
    图像分割的基本策略主要是基于图像灰度值的两个特性,即灰度的不连续性和灰度的相似性,因此图像分割方法可分为基于边缘的分割方法和基于区域的分割方法。本次实验通过完成简单的图像分割进一步加深对图像分割的理解...
  • 大纲: 1、概述 2、explode 使用例子 3、引入lateral view的原因 4、explode与lateral view使用示例1 ... 6、collect_set()函数示例 7、substr()函数示例 8、concat_ws()函数示例 1、概述 ...
  • 裂缝分割与裂缝宽度计算(正交骨架线法)

    千次阅读 多人点赞 2021-07-06 16:27:22
    可以使用 opencv 的阈值分割,或者使用 CNN 等深度学习的方法进行裂缝分割,一般得到的分割结果如下,这里不再赘述。 寻找边缘 寻找边缘有两种方法,如下 scikit-image skimage.measure.find_contours, 官方的示例...
  • SQL语句字符串分割

    2010-12-05 22:24:43
    SQL语句字符串分割
  • 从coco2017数据集中提取语义分割mask

    千次阅读 热门讨论 2020-12-30 17:35:26
    提供一个脚本,可以从coco2017数据集中提取语义分割的信息,并保存mask为png图片。
  • Mysql中group_concat()的字符串长度

    千次阅读 2017-11-13 19:43:10
    Mysql中group_concat()的字符串长度Mysql中的group_concat()函数是有长度限制的,默认为1024字节,当组合的数据过多时会出现丢失数据的情况。1.容易出现丢失数据的问题 2.容易出现丢失数据导致的解析异常问题,有...
  • 图像分割—学习笔记

    千次阅读 2019-06-20 13:28:35
    Active Contours Without Edges paper Active Contours Without Edges ...Active Contours Without Edges是一种改进的active contour图像分割或者说轮廓检测方法。作者分析已有的active contour/snakes模...
  • HALCON 语义分割的笔记(预处理)

    千次阅读 2020-06-14 10:36:31
    开始halcon语义分割的第一步是创建一个用于深度学习的语义分割的模型,在这个模型中将设置各种用于深度学习的参数。 1、模型的数据结构如下: DLDataset { 'image_dir' : 所有图像文件夹路径 'segmentation_...
  • StrArrayLength("78,2,3",") 返回值:4 三、指定符号分割字符串 返回分割后指定索引的第几个元素,象数组一样方便 CREATE function Get_StrArrayStrOfIndex ( @str varchar(1024),--要分割的字符串 @split varchar...
  • 水平集LevelSet的使用问题

    千次阅读 2018-11-07 11:16:38
    1、水平集的是一个很好的分割算法,其使用比较多的是医学图像领域。其有一些有点也有一些缺点 其会计算图片的前景灰度、背景灰度。前景是灰度值大的目标,如果前景目标太小,则会导致其分割的不准确。其算法原理跟...
  • 水平集 LevelSet 代码实现(转载) 代码来源: 非箴勿语 水平集详解与代码分析二 ...具体原理参考:hjimce 图像处理(十一)图像分割(3)泛函能量LevelSet、snake分割 http://blog.csdn.n
  • 使用find_in_set()函数轻松实现,将sign字段中含有’唱歌’属性的数据查询出来,而不是用like。 假如说想要查询多个条件,比如说既符合 唱歌 、 又符合 跳舞 的,就可以这样写: 聚合查询count总数 怎么计算总数呢?...
  • 题记——由于之前写的一个关于字符串分割的存储过程对于字符串的长度有限制,导致最终分割出来的字符有截断,失去数据原本的意义。在此又附上另一种对字符串的分割方式。这次采用函数来写,以方便以后都是用这个函数...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 112,562
精华内容 45,024
关键字:

set按长度分割