PM方程源码

cpp 

void Perona_Malik(
	unsigned char* inbuffer,
	int iter,
	double delta_t,
	double kappa,
	int option,
	int width,
	int height,
	unsigned char* outbuffer
	)
{
	double dx = 1.0;
	double dy = 1.0;
	double dd = sqrt(2.0);
	//变换数据类型,准备处理
	double* tmpbuffer1 = new double[width*height];
	double* tmpbuffer2 = new double[width*height];
	for (int kk = 0; kk < width*height; kk++)
	{
		tmpbuffer1[kk] = double(inbuffer[kk]);
		tmpbuffer2[kk] = double(inbuffer[kk]);
	}
	int i, j;
	double cN = 0.0, cS = 0.0, cE = 0.0, cW = 0.0;
	double cNE = 0.0, cSE = 0.0, cSW = 0.0, cNW = 0.0;
	double nablaN = 0.0, nablaS = 0.0, nablaE = 0.0, nablaW = 0.0;
	double nablaNE = 0.0, nablaSE = 0.0, nablaNW = 0.0, nablaSW = 0.0;
	for (int t = 0; t < iter; t++)//迭代次数
	{
		for (i = 0; i < height; i++)
		{
			for (j = 0; j < width; j++)//列
			{
				double pixel = -tmpbuffer1[i*height + j];
				nablaS = nablaE = nablaW = nablaN = pixel;
				nablaNE = nablaSE = nablaNW = nablaSW = pixel;
//八个方向上的求导
				if (i + 1 < height)//不是最后一行
					nablaN += tmpbuffer1[(i + 1)*height + j];
 
				if (i > 0)//不是第一行
					nablaS += tmpbuffer1[(i - 1)*height + j];
 
				if (j + 1 < width)//不是最后一列
					nablaE += tmpbuffer1[i*height + j + 1];
			
				if (j > 0)//不是第一列
					nablaW += tmpbuffer1[i*height + j - 1];
 
				if (i + 1 < height && j > 0)
					nablaNE += tmpbuffer1[(i + 1)*height + j -1 ];
 
				if (i  > 0 && j > 0)
					nablaSE += tmpbuffer1[(i - 1)*height + j - 1];
				
				if (i > 0 && j + 1 < width)
					nablaNW += tmpbuffer1[(i - 1)*height + j + 1];
 
				if (i + 1 < height  && j + 1 < width)
					nablaSW += tmpbuffer1[(i + 1)*height + j + 1];
 
				cN = 0.0, cS = 0.0, cE = 0.0, cW = 0.0;
				if (1 == option)//扩散函数的选择
				{
					cN = exp(-(nablaN / kappa) * (nablaN / kappa));
					cS = exp(-(nablaS / kappa) * (nablaS / kappa));
					cE = exp(-(nablaE / kappa) * (nablaE / kappa));
					cW = exp(-(nablaW / kappa) * (nablaW / kappa));
					cNE = exp(-(nablaNE / kappa) * (nablaNE / kappa));
					cSE = exp(-(nablaSE / kappa) * (nablaSE / kappa));
					cSW = exp(-(nablaSW / kappa) * (nablaSW / kappa));
					cNW = exp(-(nablaNW / kappa) * (nablaNW / kappa));
				}
				else if (2 == option)
				{
					cN = 1.0 / (1 + (nablaN / kappa) * (nablaN / kappa));
					cS = 1.0 / (1 + (nablaS / kappa) * (nablaS / kappa));
					cE = 1.0 / (1 + (nablaE / kappa) * (nablaE / kappa));
					cW = 1.0 / (1 + (nablaW / kappa) * (nablaW / kappa));
					cNE = 1.0 / (1 + (nablaNE / kappa) * (nablaNE / kappa));
					cSE = 1.0 / (1 + (nablaSE / kappa) * (nablaSE / kappa));
					cSW = 1.0 / (1 + (nablaSW / kappa) * (nablaSW / kappa));
					cNW = 1.0 / (1 + (nablaNW / kappa) * (nablaNW / kappa));
				}
 
				tmpbuffer2[i*height + j] += delta_t * ( 1.0 / (dy*dy)*cN * nablaN + 1.0 / (dy*dy)*cS * nablaS +1.0 / (dx*dx)*cE * nablaE + 1.0 / (dx*dx)*cW * nablaW +
					1.0 / (dd *dd)*cNE*nablaNE + 1.0 / (dd *dd)*cSE*nablaSE +1.0 / (dd *dd)*cSW*nablaSW + 1.0 / (dd*dd)*cNW*nablaNW);
			}
		}
		for (int kk = 0; kk < width*height; kk++)
			tmpbuffer1[kk] = tmpbuffer2[kk];
	} // 迭代结束  
 
	// 转换成图像数据 
	for (int kk = 0; kk < height*width; kk++)
		outbuffer[kk] = unsigned char(max(0, min(tmpbuffer2[kk], 255)));
 
	delete[] tmpbuffer2;
	tmpbuffer2 = NULL;
	delete[] tmpbuffer1;
	tmpbuffer1 = NULL;
}

python

import cv2
import numpy as np
import math
class anisodiff2D(object):
 
    def __init__(self, num_iter=5, delta_t=1/7, kappa=30, option=2):
 
        super(anisodiff2D, self).__init__()
 
        self.num_iter = num_iter
        self.delta_t = delta_t
        self.kappa = kappa
        self.option = option
 
        self.hN = np.array([[0, 1, 0], [0, -1, 0], [0, 0, 0]])
        self.hS = np.array([[0, 0, 0], [0, -1, 0], [0, 1, 0]])
        self.hE = np.array([[0, 0, 0], [0, -1, 1], [0, 0, 0]])
        self.hW = np.array([[0, 0, 0], [1, -1, 0], [0, 0, 0]])
        self.hNE = np.array([[0, 0, 1], [0, -1, 0], [0, 0, 0]])
        self.hSE = np.array([[0, 0, 0], [0, -1, 0], [0, 0, 1]])
        self.hSW = np.array([[0, 0, 0], [0, -1, 0], [1, 0, 0]])
        self.hNW = np.array([[1, 0, 0], [0, -1, 0], [0, 0, 0]])
 
    def fit(self, img):
 
        diff_im = img.copy()
 
        dx = 1; dy = 1; dd = math.sqrt(2)
 
        for i in range(self.num_iter):
            nablaN = cv2.filter2D(diff_im, -1, self.hN)
            nablaS = cv2.filter2D(diff_im, -1, self.hS)
            nablaW = cv2.filter2D(diff_im, -1, self.hW)
            nablaE = cv2.filter2D(diff_im, -1, self.hE)
            nablaNE = cv2.filter2D(diff_im, -1, self.hNE)
            nablaSE = cv2.filter2D(diff_im, -1, self.hSE)
            nablaSW = cv2.filter2D(diff_im, -1, self.hSW)
            nablaNW = cv2.filter2D(diff_im, -1, self.hNW)
 
            cN = 0; cS = 0; cW = 0; cE = 0; cNE = 0; cSE = 0; cSW = 0; cNW = 0
 
            if self.option == 1:
                cN = np.exp(-(nablaN/self.kappa)**2)
                cS = np.exp(-(nablaS/self.kappa)**2)
                cW = np.exp(-(nablaW/self.kappa)**2)
                cE = np.exp(-(nablaE/self.kappa)**2)
                cNE = np.exp(-(nablaNE/self.kappa)**2)
                cSE = np.exp(-(nablaSE/self.kappa)**2)
                cSW = np.exp(-(nablaSW/self.kappa)**2)
                cNW = np.exp(-(nablaNW/self.kappa)**2)
            elif self.option == 2:
                cN = 1/(1+(nablaN/self.kappa)**2)
                cS = 1/(1+(nablaS/self.kappa)**2)
                cW = 1/(1+(nablaW/self.kappa)**2)
                cE = 1/(1+(nablaE/self.kappa)**2)
                cNE = 1/(1+(nablaNE/self.kappa)**2)
                cSE = 1/(1+(nablaSE/self.kappa)**2)
                cSW = 1/(1+(nablaSW/self.kappa)**2)
                cNW = 1/(1+(nablaNW/self.kappa)**2)
 
            diff_im = diff_im + self.delta_t * (
 
                (1/dy**2)*cN*nablaN +
                (1/dy**2)*cS*nablaS +
                (1/dx**2)*cW*nablaW +
                (1/dx**2)*cE*nablaE +
 
                (1/dd**2)*cNE*nablaNE +
                (1/dd**2)*cSE*nablaSE +
                (1/dd**2)*cSW*nablaSW +
                (1/dd**2)*cNW*nablaNW
            )
 
        return diff_im

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值