实验原理

1、首先,用重心法模糊推理图像中任意一像素点的边缘隶属方向,取其最大隶属度的方向为边缘隶属方向。

2、然后,在边缘隶属方向上根据像素点附近灰度分布的特点模糊推理该点的边缘隶属度,进而实现边缘检测。

要去确定图像任一像素的边缘隶属方向,首先需要设置边缘特征来对它进行计算,得到最后的边缘方向隶属度,根据比较8个方向的边缘隶属度大小来确定他的边缘隶属方向然后,进行之后的计算该点的边缘隶属度

边缘特征的定义:

为了有效、准确地描述边缘点附近灰度分布的差异,针对图像边缘的特点,在以像素点为中心的n×n窗口中定义4种边缘特征:

  • (1)邻域隔离强度                       边缘隶属方向(1)(2)
  • (2)邻域强度方差
  • (3)法线隔离强度                       边缘隶属度(3)(4)
  • (4)边缘隶属方向强度方差

→为方便计算,特征计算时,取n=5

8个边缘隶属方向:

规定:图像中每个像素点都对应一个且只有一个该点处的边缘隶属方向。

→边缘特征1——邻域隔离强度Eg:

边缘隶属方向两侧灰度平均值之差:

  • g1、g2:边缘隶属方向两侧的灰度平均值。
  • gmax、gmin:窗口中的最大、最小灰度值。
  • Eg越小,邻域中灰度整体变化越平缓。
  • Eg越大,邻域中灰度整体变化越剧烈。

→边缘特征2——邻域强度方差Ed :

边缘隶属方向两侧灰度方差之和 :

  • Ed越小,说明在边缘隶属方向的每一侧灰度变化不大。
  • Ed越大,说明有较大的波动。

→像素点边缘隶属方向的确定:

  • 图像中的每个像素点都对应一个边缘隶属方向。
  • 根据边缘特征的定义,像素点的边缘隶属方向应该是使该点的邻域隔离强度Eg取最大值、邻域强度方差Ed取最小值的方向。
  • 像素点边缘隶属方向的确定流程包括4个步骤。

(1)假定8个方向都有可能是像素点的边缘隶属方向,分别算出每个像素点在8个方向上的邻域隔离强度Eg和邻域强度方差Ed。

(2)用Eg和Ed求出对应的隶属度。

T1、T2为[0, 1]区间上的常数,由实验确定。

(3)
①按模糊规则用重心法分别算出每个方向的隶属度dir1。

  • vl、l、m、h的参考值分别为: 0.1,0.25,0.54,0.85

②用重心法按模糊规则分别算出每个方向的隶属度dir1。

(4)将8个方向中方向隶属度最大的确定为该点的边缘隶属方向。

→边缘特征3——法线隔离强度Em :

边缘隶属方向的法线方向上中心点两侧所有灰度的平均值之差

说明在中心点的法线方向上灰度的变化程度:

  • g3、g4:法线方向上中心点两侧的均值。
  • Em越大,说明中心点为边缘点的可能性越大。
  • Em越小,可能性越小。

→边缘特征4——边缘隶属方向强度方差En :

说明边缘隶属方向上灰度的变化程度。

  • g5:边缘隶属方向上n个点的平均值。
  • En越大,在边缘隶属方向上灰度变化比较大。- 因为边缘具有一定的连续性,在边缘方向上灰度值变化不应太大,说明边缘隶属方向选得不太合理。
  • En越小,则说明边缘隶属方向选得越合理 。

→计算模糊边缘隶属度 :

  • 算出每个像素点的边缘隶属方向后,可计算其法线隔离强度Em和边缘隶属方向强度方差En。

Em越大且En越小,中心点是边缘点的可能性越大。

  • 然后,按模糊规则计算每个点的模糊边缘隶属度dir2。
  • 当dir2≥T时,像素点被判定为边缘点,否则判为非边缘点。

-T的值与图像有关,参考值0.8。


原始代码:

import matplotlib.pyplot as plt
from scipy import signal
import numpy as np
import copy as cp
import random
import math
import cv2
import collections#计算8个边缘隶属方向的邻域隔离强度Eg和邻域强度方差Ed函数
def calcEgandEd(gray,x,y,direction) :#存放这个25个灰度值的列表graylist = [] #算出这个5*5矩阵中的最大灰度值和最小灰度值for i in range (x-2,x+3):for j in range (y-2,y+3) :graylist.append(gray[i][j])gmax = max(graylist)gmin = min(graylist)#计算边缘隶属方向的邻域隔离强度Eg和邻域强度方差Ed#方向1if direction == 1:#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[1] + graylist[2] + graylist[3] + graylist[4] + graylist[7] + graylist[8] + \graylist[9] + graylist[13] + graylist[14] + graylist[19]) / (5*(5-1)/2)g2 = (graylist[5] + graylist[10] + graylist[11] + graylist[15] + graylist[16] + graylist[17] + \graylist[20] + graylist[21] + graylist[22] + graylist[23]) / (5*(5-1)/2)if gmax - gmin == 0 :Eg = 0else :Eg = (abs(g1 - g2)) / (gmax-gmin)Ed1 = ( math.pow(graylist[1]-g1,2) + math.pow(graylist[2]-g1,2)  + math.pow(graylist[3]-g1,2) + math.pow(graylist[4]-g1,2) + math.pow(graylist[7]-g1,2) + \math.pow(graylist[8]-g1,2) + math.pow(graylist[9]-g1,2) + math.pow(graylist[13]-g1,2) + math.pow(graylist[14]-g1,2) + math.pow(graylist[19]-g1,2) )Ed2 = ( math.pow(graylist[5]-g2,2) + math.pow(graylist[10]-g2,2)  + math.pow(graylist[11]-g2,2) + math.pow(graylist[15]-g2,2) + math.pow(graylist[16]-g2,2) + \math.pow(graylist[17]-g2,2) + math.pow(graylist[20]-g2,2) + math.pow(graylist[21]-g2,2) + math.pow(graylist[22]-g2,2) + math.pow(graylist[23]-g2,2) )if gmax - gmin == 0 :Ed = 0else :Ed = (Ed1 + Ed2) / (5*(5-1)*math.pow(gmax-gmin,2))return (Eg,Ed,1)#方向2if direction == 2:#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[0] + graylist[1] + graylist[2] + graylist[3] + graylist[4] + graylist[6] + graylist[7] + \graylist[8] + graylist[9] + graylist[14]) / (5*(5-1)/2)g2 = (graylist[10] + graylist[15] + graylist[16] + graylist[17] + graylist[18] + graylist[20] + \graylist[21] + graylist[22] + graylist[23] + graylist[24]) / (5*(5-1)/2)if gmax - gmin == 0 :Eg = 0else :Eg = (abs(g1 - g2)) / (gmax-gmin)Ed1 = ( math.pow(graylist[0]-g1,2) + math.pow(graylist[1]-g1,2)  + math.pow(graylist[2]-g1,2) + math.pow(graylist[3]-g1,2) + math.pow(graylist[4]-g1,2) + \math.pow(graylist[6]-g1,2) + math.pow(graylist[7]-g1,2) + math.pow(graylist[8]-g1,2) + math.pow(graylist[9]-g1,2) + math.pow(graylist[14]-g1,2) )Ed2 = ( math.pow(graylist[10]-g2,2) + math.pow(graylist[15]-g2,2)  + math.pow(graylist[16]-g2,2) + math.pow(graylist[17]-g2,2) + math.pow(graylist[18]-g2,2) + \math.pow(graylist[20]-g2,2) + math.pow(graylist[21]-g2,2) + math.pow(graylist[22]-g2,2) + math.pow(graylist[23]-g2,2) + math.pow(graylist[24]-g2,2) )if gmax - gmin == 0 :Ed = 0else :Ed = (Ed1 + Ed2) / (5*(5-1)*math.pow(gmax-gmin,2))return (Eg,Ed,2)#方向3if direction == 3:#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[0] + graylist[1] + graylist[2] + graylist[3] + graylist[4] + graylist[5] + graylist[6] + \graylist[7] + graylist[8] + graylist[9]) / (5*(5-1)/2)g2 = (graylist[15] + graylist[16] + graylist[17] + graylist[18] + graylist[19] + graylist[20] + \graylist[21] + graylist[22] + graylist[23] + graylist[24]) / (5*(5-1)/2)if gmax - gmin == 0 :Eg = 0else :Eg = (abs(g1 - g2)) / (gmax-gmin)Ed1 = ( math.pow(graylist[0]-g1,2) + math.pow(graylist[1]-g1,2)  + math.pow(graylist[2]-g1,2) + math.pow(graylist[3]-g1,2) + math.pow(graylist[4]-g1,2) + \math.pow(graylist[5]-g1,2) + math.pow(graylist[6]-g1,2) + math.pow(graylist[7]-g1,2) + math.pow(graylist[8]-g1,2) + math.pow(graylist[9]-g1,2) )Ed2 = ( math.pow(graylist[15]-g2,2) + math.pow(graylist[16]-g2,2)  + math.pow(graylist[17]-g2,2) + math.pow(graylist[18]-g2,2) + math.pow(graylist[19]-g2,2) + \math.pow(graylist[20]-g2,2) + math.pow(graylist[21]-g2,2) + math.pow(graylist[22]-g2,2) + math.pow(graylist[23]-g2,2) + math.pow(graylist[24]-g2,2) )if gmax - gmin == 0 :Ed = 0else :Ed = (Ed1 + Ed2) / (5*(5-1)*math.pow(gmax-gmin,2))return (Eg,Ed,3)#方向4if direction == 4:#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[0] + graylist[1] + graylist[2] + graylist[3] + graylist[4] + graylist[5] + graylist[6] + \graylist[7] + graylist[8] + graylist[10]) / (5*(5-1)/2)g2 = (graylist[14] + graylist[16] + graylist[17] + graylist[18] + graylist[19] + graylist[20] + \graylist[21] + graylist[22] + graylist[23] + graylist[24]) / (5*(5-1)/2)if gmax - gmin == 0 :Eg = 0else :Eg = (abs(g1 - g2)) / (gmax-gmin)Ed1 = ( math.pow(graylist[0]-g1,2) + math.pow(graylist[1]-g1,2)  + math.pow(graylist[2]-g1,2) + math.pow(graylist[3]-g1,2) + math.pow(graylist[4]-g1,2) + \math.pow(graylist[5]-g1,2) + math.pow(graylist[6]-g1,2) + math.pow(graylist[7]-g1,2) + math.pow(graylist[8]-g1,2) + math.pow(graylist[10]-g1,2) )Ed2 = ( math.pow(graylist[14]-g2,2) + math.pow(graylist[16]-g2,2)  + math.pow(graylist[17]-g2,2) + math.pow(graylist[18]-g2,2) + math.pow(graylist[19]-g2,2) + \math.pow(graylist[20]-g2,2) + math.pow(graylist[21]-g2,2) + math.pow(graylist[22]-g2,2) + math.pow(graylist[23]-g2,2) + math.pow(graylist[24]-g2,2) )if gmax - gmin == 0 :Ed = 0else :Ed = (Ed1 + Ed2) / (5*(5-1)*math.pow(gmax-gmin,2))return (Eg,Ed,4)#方向5if direction == 5:#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[0] + graylist[1] + graylist[2] + graylist[3] + graylist[5] + graylist[6] + graylist[7] + \graylist[10] + graylist[11] + graylist[15]) / (5*(5-1)/2)g2 = (graylist[9] + graylist[13] + graylist[14] + graylist[17] + graylist[18] + graylist[19] + \graylist[21] + graylist[22] + graylist[23] + graylist[24]) / (5*(5-1)/2)if gmax - gmin == 0 :Eg = 0else :Eg = (abs(g1 - g2)) / (gmax-gmin)Ed1 = ( math.pow(graylist[0]-g1,2) + math.pow(graylist[1]-g1,2)  + math.pow(graylist[2]-g1,2) + math.pow(graylist[3]-g1,2) + math.pow(graylist[5]-g1,2) + \math.pow(graylist[6]-g1,2) + math.pow(graylist[7]-g1,2) + math.pow(graylist[10]-g1,2) + math.pow(graylist[11]-g1,2) + math.pow(graylist[15]-g1,2) )Ed2 = ( math.pow(graylist[9]-g2,2) + math.pow(graylist[13]-g2,2)  + math.pow(graylist[14]-g2,2) + math.pow(graylist[17]-g2,2) + math.pow(graylist[18]-g2,2) + \math.pow(graylist[19]-g2,2) + math.pow(graylist[21]-g2,2) + math.pow(graylist[22]-g2,2) + math.pow(graylist[23]-g2,2) + math.pow(graylist[24]-g2,2) )if gmax - gmin == 0 :Ed = 0else :Ed = (Ed1 + Ed2) / (5*(5-1)*math.pow(gmax-gmin,2))return (Eg,Ed,5)#方向6if direction == 6:#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[0] + graylist[1] + graylist[2] + graylist[5] + graylist[6] + graylist[10] + graylist[11] + \graylist[15] + graylist[16] + graylist[20]) / (5*(5-1)/2)g2 = (graylist[4] + graylist[8] + graylist[9] + graylist[13] + graylist[14] + graylist[18] + \graylist[19] + graylist[22] + graylist[23] + graylist[24]) / (5*(5-1)/2)if gmax - gmin == 0 :Eg = 0else :Eg = (abs(g1 - g2)) / (gmax-gmin)Ed1 = ( math.pow(graylist[0]-g1,2) + math.pow(graylist[1]-g1,2)  + math.pow(graylist[2]-g1,2) + math.pow(graylist[5]-g1,2) + math.pow(graylist[6]-g1,2) + \math.pow(graylist[10]-g1,2) + math.pow(graylist[11]-g1,2) + math.pow(graylist[15]-g1,2) + math.pow(graylist[16]-g1,2) + math.pow(graylist[20]-g1,2) )Ed2 = ( math.pow(graylist[4]-g2,2) + math.pow(graylist[8]-g2,2)  + math.pow(graylist[9]-g2,2) + math.pow(graylist[13]-g2,2) + math.pow(graylist[14]-g2,2) + \math.pow(graylist[18]-g2,2) + math.pow(graylist[19]-g2,2) + math.pow(graylist[22]-g2,2) + math.pow(graylist[23]-g2,2) + math.pow(graylist[24]-g2,2) )if gmax - gmin == 0 :Ed = 0else :Ed = (Ed1 + Ed2) / (5*(5-1)*math.pow(gmax-gmin,2))return (Eg,Ed,6)#方向7if direction == 7:#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[0] + graylist[1] + graylist[5] + graylist[6] + graylist[10] + graylist[11] + graylist[15] + \graylist[16] + graylist[20] + graylist[21]) / (5*(5-1)/2)g2 = (graylist[3] + graylist[4] + graylist[8] + graylist[9] + graylist[13] + graylist[14] + \graylist[18] + graylist[19] + graylist[23] + graylist[24]) / (5*(5-1)/2)if gmax - gmin == 0 :Eg = 0else :Eg = (abs(g1 - g2)) / (gmax-gmin)Ed1 = ( math.pow(graylist[0]-g1,2) + math.pow(graylist[1]-g1,2)  + math.pow(graylist[5]-g1,2) + math.pow(graylist[6]-g1,2) + math.pow(graylist[10]-g1,2) + \math.pow(graylist[11]-g1,2) + math.pow(graylist[15]-g1,2) + math.pow(graylist[16]-g1,2) + math.pow(graylist[20]-g1,2) + math.pow(graylist[21]-g1,2) )Ed2 = ( math.pow(graylist[3]-g2,2) + math.pow(graylist[4]-g2,2)  + math.pow(graylist[8]-g2,2) + math.pow(graylist[9]-g2,2) + math.pow(graylist[13]-g2,2) + \math.pow(graylist[14]-g2,2) + math.pow(graylist[18]-g2,2) + math.pow(graylist[19]-g2,2) + math.pow(graylist[23]-g2,2) + math.pow(graylist[24]-g2,2) )if gmax - gmin == 0 :Ed = 0else :Ed = (Ed1 + Ed2) / (5*(5-1)*math.pow(gmax-gmin,2))return (Eg,Ed,7)#方向8if direction == 8:#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[0] + graylist[5] + graylist[6] + graylist[10] + graylist[11] + graylist[15] + graylist[16] + \graylist[20] + graylist[21] + graylist[22]) / (5*(5-1)/2)g2 = (graylist[2] + graylist[3] + graylist[4] + graylist[8] + graylist[9] + graylist[13] + \graylist[14] + graylist[18] + graylist[19] + graylist[24]) / (5*(5-1)/2)if gmax - gmin == 0 :Eg = 0else :Eg = (abs(g1 - g2)) / (gmax-gmin)Ed1 = ( math.pow(graylist[0]-g1,2) + math.pow(graylist[5]-g1,2)  + math.pow(graylist[6]-g1,2) + math.pow(graylist[10]-g1,2) + math.pow(graylist[11]-g1,2) + \math.pow(graylist[15]-g1,2) + math.pow(graylist[16]-g1,2) + math.pow(graylist[20]-g1,2) + math.pow(graylist[21]-g1,2) + math.pow(graylist[22]-g1,2) )Ed2 = ( math.pow(graylist[2]-g2,2) + math.pow(graylist[3]-g2,2)  + math.pow(graylist[4]-g2,2) + math.pow(graylist[8]-g2,2) + math.pow(graylist[9]-g2,2) + \math.pow(graylist[13]-g2,2) + math.pow(graylist[14]-g2,2) + math.pow(graylist[18]-g2,2) + math.pow(graylist[19]-g2,2) + math.pow(graylist[24]-g2,2) )if gmax - gmin == 0 :Ed = 0else :Ed = (Ed1 + Ed2) / (5*(5-1)*math.pow(gmax-gmin,2))return (Eg,Ed,8)#用Eg和Ed求出对应的隶属度
def clcbelongValue(Eg,Ed,direction,T1=0.8,T2=0.8):     #T1、T2为[0, 1]区间上的常数,由实验确定if  Eg == 0 :Egl = 0Egs = 1elif 0 < Eg <= T1 :Egl = Eg / T1Egs = 1 - (Eg / T1)else :Egl = 1Egs = 0 if  Ed == 0 :Edl = 0Eds = 1elif 0 < Ed <= T2 :Edl = Ed / T2Eds = 1 - (Ed / T2)else :Edl = 1Eds = 0 #vl、l、m、h的参考值分别为: 0.1,0.25,0.54,0.85vl = 0.05    #很低l = 0.2    #低m = 0.5    #中h = 0.9    #高dir1 = ( min(Egs,Edl)*vl + min(Egs,Eds)*l + min(Egl,Edl)*m + min(Egl,Eds)*h ) / (min(Egs,Edl) + min(Egs,Eds) + min(Egl,Edl) + min(Egl,Eds))return (dir1,direction)#计算法线隔离强度Em和边缘隶属方向强度方差En
def calcEmandEn(gray,x,y,direction) :#存放这个25个灰度值的列表graylist = [] #算出这个5*5矩阵中的最大灰度值和最小灰度值for i in range (x-2,x+3):for j in range (y-2,y+3) :graylist.append(gray[i][j])gmax = max(graylist)gmin = min(graylist)#如果他的边缘隶属方向为方向1,之后类推if direction == 1 :#g1、g2:法线方向上中心点两侧的均值#g3:边缘隶属方向上n个点的平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[0] + graylist[1] + graylist[2] + graylist[3] + graylist[5] + graylist[6] + graylist[7] + \graylist[10] + graylist[11] + graylist[15]) / (5*(5-1)/2)g2 = (graylist[9] + graylist[13] + graylist[14] + graylist[17] + graylist[18] + graylist[19] + \graylist[21] + graylist[22] + graylist[23] + graylist[24]) / (5*(5-1)/2)if gmax - gmin == 0 :Em = 0else :Em = (abs(g1 - g2)) / (gmax-gmin)g3 = (graylist[4] + graylist[8] + graylist[12] + graylist[16] + graylist[20]) / 5En1 = math.pow(graylist[4]-g3,2) + math.pow(graylist[8]-g3,2) + math.pow(graylist[12]-g3,2) + math.pow(graylist[16]-g3,2) + math.pow(graylist[20]-g3,2)if gmax - gmin == 0 :En = 0else :En = En1 / (5*math.pow(gmax - gmin,2))return (Em,En)elif direction == 2 :#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[0] + graylist[1] + graylist[2] + graylist[5] + graylist[6] + graylist[10] + graylist[11] + \graylist[15] + graylist[16] + graylist[20]) / (5*(5-1)/2)g2 = (graylist[4] + graylist[8] + graylist[9] + graylist[13] + graylist[14] + graylist[18] + \graylist[19] + graylist[22] + graylist[23] + graylist[24]) / (5*(5-1)/2)if gmax - gmin == 0 :Em = 0else :Em = (abs(g1 - g2)) / (gmax-gmin)g3 = (graylist[3] + graylist[7] + graylist[12] + graylist[17] + graylist[21]) / 5En1 = math.pow(graylist[3]-g3,2) + math.pow(graylist[7]-g3,2) + math.pow(graylist[12]-g3,2) + math.pow(graylist[17]-g3,2) + math.pow(graylist[21]-g3,2)if gmax - gmin == 0 :En = 0else :En = En1 / (5*math.pow(gmax - gmin,2))return (Em,En)elif direction == 3 :#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[0] + graylist[1] + graylist[5] + graylist[6] + graylist[10] + graylist[11] + graylist[15] + \graylist[16] + graylist[20] + graylist[21]) / (5*(5-1)/2)g2 = (graylist[3] + graylist[4] + graylist[8] + graylist[9] + graylist[13] + graylist[14] + \graylist[18] + graylist[19] + graylist[23] + graylist[24]) / (5*(5-1)/2)if gmax - gmin == 0 :Em = 0else :Em = (abs(g1 - g2)) / (gmax-gmin)g3 = (graylist[2] + graylist[7] + graylist[12] + graylist[17] + graylist[22]) / 5En1 = math.pow(graylist[2]-g3,2) + math.pow(graylist[7]-g3,2) + math.pow(graylist[12]-g3,2) + math.pow(graylist[17]-g3,2) + math.pow(graylist[22]-g3,2)if gmax - gmin == 0 :En = 0else :En = En1 / (5*math.pow(gmax - gmin,2))return (Em,En)elif direction == 4 :#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[0] + graylist[5] + graylist[6] + graylist[10] + graylist[11] + graylist[15] + graylist[16] + \graylist[20] + graylist[21] + graylist[22]) / (5*(5-1)/2)g2 = (graylist[2] + graylist[3] + graylist[4] + graylist[8] + graylist[9] + graylist[13] + \graylist[14] + graylist[18] + graylist[19] + graylist[24]) / (5*(5-1)/2)if gmax - gmin == 0 :Em = 0else :Em = (abs(g1 - g2)) / (gmax-gmin)g3 = (graylist[1] + graylist[7] + graylist[12] + graylist[17] + graylist[23]) / 5En1 = math.pow(graylist[1]-g3,2) + math.pow(graylist[7]-g3,2) + math.pow(graylist[12]-g3,2) + math.pow(graylist[17]-g3,2) + math.pow(graylist[23]-g3,2)if gmax - gmin == 0 :En = 0else :En = En1 / (5*math.pow(gmax - gmin,2))return (Em,En)elif direction == 5 :#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[1] + graylist[2] + graylist[3] + graylist[4] + graylist[7] + graylist[8] + \graylist[9] + graylist[13] + graylist[14] + graylist[19]) / (5*(5-1)/2)g2 = (graylist[5] + graylist[10] + graylist[11] + graylist[15] + graylist[16] + graylist[17] + \graylist[20] + graylist[21] + graylist[22] + graylist[23]) / (5*(5-1)/2)if gmax - gmin == 0 :Em = 0else :Em = (abs(g1 - g2)) / (gmax-gmin)g3 = (graylist[0] + graylist[6] + graylist[12] + graylist[18] + graylist[24]) / 5En1 = math.pow(graylist[0]-g3,2) + math.pow(graylist[6]-g3,2) + math.pow(graylist[12]-g3,2) + math.pow(graylist[18]-g3,2) + math.pow(graylist[24]-g3,2)if gmax - gmin == 0 :En = 0else :En = En1 / (5*math.pow(gmax - gmin,2))return (Em,En)elif direction == 6 :#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[0] + graylist[1] + graylist[2] + graylist[3] + graylist[4] + graylist[6] + graylist[7] + \graylist[8] + graylist[9] + graylist[14]) / (5*(5-1)/2)g2 = (graylist[10] + graylist[15] + graylist[16] + graylist[17] + graylist[18] + graylist[20] + \graylist[21] + graylist[22] + graylist[23] + graylist[24]) / (5*(5-1)/2)if gmax - gmin == 0 :Em = 0else :Em = (abs(g1 - g2)) / (gmax-gmin)g3 = (graylist[5] + graylist[11] + graylist[12] + graylist[13] + graylist[19]) / 5En1 = math.pow(graylist[5]-g3,2) + math.pow(graylist[11]-g3,2) + math.pow(graylist[12]-g3,2) + math.pow(graylist[13]-g3,2) + math.pow(graylist[19]-g3,2)if gmax - gmin == 0 :En = 0else :En = En1 / (5*math.pow(gmax - gmin,2))return (Em,En)elif direction == 7 :#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[0] + graylist[1] + graylist[2] + graylist[3] + graylist[4] + graylist[5] + graylist[6] + \graylist[7] + graylist[8] + graylist[9]) / (5*(5-1)/2)g2 = (graylist[15] + graylist[16] + graylist[17] + graylist[18] + graylist[19] + graylist[20] + \graylist[21] + graylist[22] + graylist[23] + graylist[24]) / (5*(5-1)/2)if gmax - gmin == 0 :Em = 0else :Em = (abs(g1 - g2)) / (gmax-gmin)g3 = (graylist[10] + graylist[11] + graylist[12] + graylist[13] + graylist[14]) / 5En1 = math.pow(graylist[10]-g3,2) + math.pow(graylist[11]-g3,2) + math.pow(graylist[12]-g3,2) + math.pow(graylist[13]-g3,2) + math.pow(graylist[14]-g3,2)if gmax - gmin == 0 :En = 0else :En = En1 / (5*math.pow(gmax - gmin,2))return (Em,En)elif direction == 8 :#g1、g2:边缘隶属方向两侧的灰度平均值#gmax、gmin:窗口中的最大、最小灰度值g1 = (graylist[0] + graylist[1] + graylist[2] + graylist[3] + graylist[4] + graylist[5] + graylist[6] + \graylist[7] + graylist[8] + graylist[10]) / (5*(5-1)/2)g2 = (graylist[14] + graylist[16] + graylist[17] + graylist[18] + graylist[19] + graylist[20] + \graylist[21] + graylist[22] + graylist[23] + graylist[24]) / (5*(5-1)/2)if gmax - gmin == 0 :Em = 0else :Em = (abs(g1 - g2)) / (gmax-gmin)g3 = (graylist[9] + graylist[11] + graylist[12] + graylist[13] + graylist[15]) / 5En1 = math.pow(graylist[9]-g3,2) + math.pow(graylist[11]-g3,2) + math.pow(graylist[12]-g3,2) + math.pow(graylist[13]-g3,2) + math.pow(graylist[15]-g3,2)if gmax - gmin == 0 :En = 0else :En = En1 / (5*math.pow(gmax - gmin,2))return (Em,En)#用Em和En计算模糊边缘隶属度
def clcbelongValue2(Em,En,T3=1,T4=0.4):     #T1、T2为[0, 1]区间上的常数,由实验确定if  Em == 0 :Eml = 0Ems = 1elif 0 < Em <= T3 :Eml = Em / T3Ems = 1 - (Em / T3)else :Eml = 1Ems = 0 if  En == 0 :Enl = 0Ens = 1elif 0 < En <= T4 :Enl = En / T4Ens = 1 - (En / T4)else :Enl = 1Ens = 0 #vl、l、m、h的参考值分别为:0.1,0.3,0.55,0.8vl = 0.1   #很低l = 0.3      #低m = 0.5  #中h = 0.9     #高dir2 = ( min(Ems,Enl)*vl + min(Ems,Ens)*l + min(Eml,Enl)*m + min(Eml,Ens)*h ) / (min(Ems,Enl) + min(Ems,Ens) + min(Eml,Enl) + min(Eml,Ens))return dir2def MAIN():image = cv2.imread(r"D:\Code\Python\4.png")#画出灰度图gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)#cv2.imshow("gray",gray)gray2=np.array([[0 for i in range(gray.shape[1])] for i in range(gray.shape[0])], dtype='float') #cv2.imshow("old_img",gray)for x in range (2,gray.shape[0]-2) :for y in range (2,gray.shape[1]-2) :#计算该点8个边缘隶属方向的邻域隔离强度Eg和邻域强度方差Ed(Eg1,Ed1,direction1) = calcEgandEd(gray,x,y,1)(Eg2,Ed2,direction2) = calcEgandEd(gray,x,y,2)(Eg3,Ed3,direction3) = calcEgandEd(gray,x,y,3)(Eg4,Ed4,direction4) = calcEgandEd(gray,x,y,4)(Eg5,Ed5,direction5) = calcEgandEd(gray,x,y,5)(Eg6,Ed6,direction6) = calcEgandEd(gray,x,y,6)(Eg7,Ed7,direction7) = calcEgandEd(gray,x,y,7)(Eg8,Ed8,direction8) = calcEgandEd(gray,x,y,8)#用Eg和Ed计算该点8个边缘隶属方向对应的隶属度(dir1,position1)=clcbelongValue(Eg1,Ed1,direction1)(dir2,position2)=clcbelongValue(Eg2,Ed2,direction2)(dir3,position3)=clcbelongValue(Eg3,Ed3,direction3)(dir4,position4)=clcbelongValue(Eg4,Ed4,direction4)(dir5,position5)=clcbelongValue(Eg5,Ed5,direction5)(dir6,position6)=clcbelongValue(Eg6,Ed6,direction6)(dir7,position7)=clcbelongValue(Eg7,Ed7,direction7)(dir8,position8)=clcbelongValue(Eg8,Ed8,direction8)#将得到的隶属度和方向组合成一个字典,进行排序l = [(dir1,position1),(dir2,position2),(dir3,position3),(dir4,position4),(dir5,position5),(dir6,position6),(dir7,position7),(dir8,position8)]l = dict(l)l = sorted(l.items(),key=lambda item:item[0],reverse=True)(dir_final,direction_final) = l[0]#计算该点法线隔离强度Em和边缘隶属方向强度方差En (Em,En) = calcEmandEn(gray,x,y,direction_final)dir_final_final = clcbelongValue2(Em,En)#T的值与图像有关,参考值0.15T = 0.14if dir_final_final >= T :#说明这个点是边缘点gray2[x][y] = 0else :gray2[x][y] = 255cv2.imshow('Edge processing',gray2)cv2.waitKey(0)if __name__ == "__main__":MAIN()

算法有瑕疵,所以效果不完美:
                                             

(自己编写函数)Python + Opencv 图像边缘检测(模糊算法【老师给的ppt中原理是这样的,但是还有很多不明白,有很多参数老师没说怎么算,只说了每张图片不一样】)相关推荐

  1. python opencv图像加密解密算法优化

    今天给大家带来的是图像加密解密算法的优化 这是我的设计思路 import cv2 import numpy as np aaa=cv2.imread("xxx.jpg",0) // ...

  2. python opencv图像二值化函数_python opencv 二值化 计算白色像素点的实例

    python opencv 二值化 计算白色像素点的实例 贴部分代码 #! /usr/bin/env python # -*- coding: utf-8 -*- import cv2 import ...

  3. 【Python+OpenCV 图像透视变换 warpPerspective函数】

    Python+OpenCV 图像透视变换 warpPerspective函数 1.函数介绍 2.代码实例 3.实现效果 1.函数介绍 warpPerspective():对图像进行透视变换.简单来说, ...

  4. python实现运动模糊图像_OpenCV+Python实现图像运动模糊和高斯模糊

    原标题:OpenCV+Python实现图像运动模糊和高斯模糊 运动模糊:由于相机和物体之间的相对运动造成的模糊,又称为动态模糊 OpenCV+Python实现运动模糊,主要用到的函数是cv2.filt ...

  5. python opencv 图像膨胀

    python opencv 图像膨胀 代码: import cv2 import numpy as np # 图像膨胀 def dilate_img(img,a,iterations):kernel ...

  6. python opencv 图像旋转

    python opencv 图像旋转 原图 顺时针旋转 代码: import cv2 path = '2.jpg' img = cv2.imread(path,1) trans_img = cv2.t ...

  7. 【Python+OpenCV 图像的缩放和裁剪】

    Python+OpenCV 图像的缩放和裁剪 代码部分 实现效果 代码部分 import cv2 import numpy as npimg = cv2.imread("Photos/1.b ...

  8. Python+OpenCV:基于分水岭算法的图像分割(Image Segmentation with Watershed Algorithm)

    Python+OpenCV:基于分水岭算法的图像分割(Image Segmentation with Watershed Algorithm) ############################ ...

  9. OpenCV图像监视:在Visual Studio调试器中查看内存中图像

    OpenCV图像监视:在Visual Studio调试器中查看内存中图像 图像监视:在Visual Studio调试器中查看内存中图像 先决条件 安装 例子 更多的 图像监视:在Visual Stud ...

最新文章

  1. Linux System and Performance Monitoring
  2. 对hash签名失败_详解Vue开发微信H5微信分享签名失败问题解决方案
  3. 邓迎春绘画201702作品08
  4. 通过在操作系统中实际操作,学习和理解 Unicode 编码相关知识
  5. arkit技术介绍_面向移动AR的触觉技术:如何以“触摸”感增强ARKit应用
  6. 数据算法排序之归并排序
  7. springmvc默认方法名为映射名_SpringIoC和SpringMVC的快速入门
  8. sql server新增列_SQL Server 2016安装中的新增功能?
  9. socket怎么同时监听两个端口_三十岁了,我同时爱上两个男人,我现在不知道怎么办...
  10. 题解【[BJOI2012]算不出的等式】
  11. ZOJ 3256 Tour in the Castle(插头DP-按行递推—矩阵)
  12. 使用Struts框架,实现用户登陆功能
  13. word vba 控制光标常用代码
  14. 计算机视觉论文-2021-04-06
  15. 耗子大叔分享的软件设计原则
  16. 设计模式——代理模式详解(Java版)
  17. QQ浏览器app应用专区推荐系统
  18. Android破解与防破解
  19. bzoj1529: [POI2005]ska Piggy banks
  20. NetApp 数据保护解决方案

热门文章

  1. 数字图像处理 离散图象变换
  2. BW顾问进阶:BW服务器访问文件数据源,处理链调度抽取方案
  3. 人员定位及轨迹管理方案
  4. BUUCTF-[QCTF2018]X-man-Keyword
  5. 命不好,因为你同床共枕的人
  6. Android中如何检测重力感应变化:Sensor和SensorManager
  7. hbilderx 扫一扫_【报Bug】hbuilder 扫一扫从相册中选图的图片扫码识别不出来
  8. 《2022元宇宙黑客松》ThreeX专场
  9. 【CCF 201712-4】行车路线(Dijkstra 80分)
  10. 如何在谷歌地球上画路线或者运动轨迹?根据纬经高信息在谷歌地球Google earth中画运动轨迹,首先将Excel文件纬经高信息转换为.csv文件,再转换为.kml文件,最终在谷歌地球中显示。