首页 > 编程语言 >canny 算法 python实现, 双边滤波--自适应阈值改进--形态学操作

canny 算法 python实现, 双边滤波--自适应阈值改进--形态学操作

时间:2024-11-13 19:49:33浏览次数:3  
标签:weight -- image dfs python range canny np gradients

# -*- coding: utf-8 -*-
import numpy as np
import cv2
import os
import csv
#高斯滤波
def smooth(image, sigma=1.4, length=5):
    # Compute gaussian filter
    k = length // 2
    gaussian = np.zeros([length, length])
    for i in range(length):
        for j in range(length):
            gaussian[i, j] = np.exp(-((i - k) ** 2 + (j - k) ** 2) / (2 * sigma ** 2))
    gaussian /= 2 * np.pi * sigma ** 2
    gaussian = gaussian / np.sum(gaussian)

    W, H = image.shape
    new_image = np.zeros([W - k * 2, H - k * 2])

    for i in range(W - 2 * k):
        for j in range(H - 2 * k):
            new_image[i, j] = np.sum(image[i:i + length, j:j + length] * gaussian)

    new_image = np.uint8(new_image)

    return new_image


# 双边滤波
def bilateral_filter(image, d=3, sigmaColor=20, sigmaSpace=40):
    # 应用双边滤波
    filtered_image = cv2.bilateralFilter(image, d, sigmaColor, sigmaSpace)
    return filtered_image

#梯度
def get_gradient_and_direction(image):
    Gx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
    Gy = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])

    W, H = image.shape
    gradients = np.zeros([W - 2, H - 2])
    direction = np.zeros([W - 2, H - 2])

    for i in range(W - 2):
        for j in range(H - 2):
            dx = np.sum(image[i:i + 3, j:j + 3] * Gx)
            dy = np.sum(image[i:i + 3, j:j + 3] * Gy)
            gradients[i, j] = np.sqrt(dx ** 2 + dy ** 2)
            if dx == 0:
                direction[i, j] = np.pi / 2
            else:
                direction[i, j] = np.arctan(dy / dx)

    gradients = np.uint8(gradients)

    return gradients, direction


# 自适应阈值
def otsu_thresholds(image, high_ratio=0.5):
    hight_value, otsu_thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    high_thresh = hight_value
    low_thresh = int(high_ratio * high_thresh)
    return low_thresh, high_thresh


#非极大抑制
def NMS(gradients, direction):
    W, H = gradients.shape
    nms = np.copy(gradients[1:-1, 1:-1])

    for i in range(1, W - 1):
        for j in range(1, H - 1):
            theta = direction[i, j]
            weight = np.tan(theta)
            if theta > np.pi / 4:
                d1 = [0, 1]
                d2 = [1, 1]
                weight = 1 / weight
            elif theta >= 0:
                d1 = [1, 0]
                d2 = [1, 1]
            elif theta >= - np.pi / 4:
                d1 = [1, 0]
                d2 = [1, -1]
                weight *= -1
            else:
                d1 = [0, -1]
                d2 = [1, -1]
                weight = -1 / weight

            g1 = gradients[i + d1[0], j + d1[1]]
            g2 = gradients[i + d2[0], j + d2[1]]
            g3 = gradients[i - d1[0], j - d1[1]]
            g4 = gradients[i - d2[0], j - d2[1]]

            grade_count1 = g1 * weight + g2 * (1 - weight)
            grade_count2 = g3 * weight + g4 * (1 - weight)

            if grade_count1 > gradients[i, j] or grade_count2 > gradients[i, j]:
                nms[i - 1, j - 1] = 0

    return nms

#高低阈值
def double_threshold(nms, threshold1, threshold2):
    visited = np.zeros_like(nms)
    output_image = nms.copy()
    W, H = output_image.shape

    def dfs(i, j):
        if i >= W or i < 0 or j >= H or j < 0 or visited[i, j] == 1:
            return
        visited[i, j] = 1
        if output_image[i, j] > threshold1:
            output_image[i, j] = 255
            dfs(i - 1, j - 1)
            dfs(i - 1, j)
            dfs(i - 1, j + 1)
            dfs(i, j - 1)
            dfs(i, j + 1)
            dfs(i + 1, j - 1)
            dfs(i + 1, j)
            dfs(i + 1, j + 1)
        else:
            output_image[i, j] = 0

    for w in range(W):
        for h in range(H):
            if visited[w, h] == 1:
                continue
            if output_image[w, h] >= threshold2:
                dfs(w, h)
            elif output_image[w, h] <= threshold1:
                output_image[w, h] = 0
                visited[w, h] = 1

    for w in range(W):
        for h in range(H):
            if visited[w, h] == 0:
                output_image[w, h] = 0
    return output_image

#形态学-膨胀-闭操作
def dilate_close(image, kernel_dilaterd=(3,3), kernel_close=(3,3)):
    image = cv2.dilate(image,  np.ones(kernel_dilaterd, np.uint8), iterations=1)  #膨胀
    closed= cv2.morphologyEx(image, cv2.MORPH_CLOSE, np.ones(kernel_close, np.uint8), iterations=1)  #闭操作
    return closed

#改进的Canny  (传灰度图)
def canny_binary_filer_otus(image):
    smoothed_image = smooth(image)   #高斯滤波
    #smoothed_image = bilateral_filter(image, d=9, sigmaColor=35, sigmaSpace=75)  # 双边滤波
    gradients, direction = get_gradient_and_direction(smoothed_image)  # 梯度计算
    nms = NMS(gradients, direction)  # 非极大抑制
    low_thresh, high_thresh = otsu_thresholds(smoothed_image, 0.5)
    output_image = double_threshold(nms, low_thresh, high_thresh)  # 双阈值
    output_image = dilate_close(output_image, kernel_dilaterd=(3, 3), kernel_close=(3, 3))  # 形态学(膨胀-闭操作)
    return output_image

标签:weight,--,image,dfs,python,range,canny,np,gradients
From: https://blog.csdn.net/m0_58054476/article/details/143750944

相关文章

  • Linux基础笔试练习题笔记(1)
    Linux系统中建立一个新文件可以使用的命令为?A.chmodB.moreC.cpD.touch答案解析:chmod命令是控制用户对文件的权限的命令;more命令类似cat,不过会以一页一页的形式显示,更方便使用者逐页阅读;cp(copyfile)命令主要用于复制文件或目录;touch命令用于修改文件或者目录的时间......
  • 【Jenkins】如何在Pipeline中使用环境变量?
    在JenkinsPipeline中使用环境变量是一种常见的做法,可以帮助你在不同的构建步骤之间传递信息,或者为你的构建提供可配置的选项。环境变量可以在Jenkins的系统级别定义,也可以在Pipeline脚本中直接定义。在Pipeline中使用环境变量1.系统级别的环境变量你可以在Jenkins的全......
  • Python中的面向对象编程,类,对象,封装,继承,多态
    一、面向对象编程1.面向过程和面向对象面向过程和面向对象都是一种编程方式,只不过再设计上有区别。面向过程C语言细分成每一个过程优点:简单直观、性能高效、代码简洁。缺点:不易维护、不易扩展、代码重用性低。面向对象python、java、C++要使用某个功能,直接找到对应的......
  • 二分查找(折半查找)函数与非函数写法代码介绍及其优缺点 C语言
    什么是二分查找?二分查找也叫折半查找 在有序的数组中查找目标的方法需要借助中间元素与目标值的比较来逐步缩小范围一直到找到目标元素或者不存在为止查找的步骤↓1确定左右端点的下标值(注:数组下标从0开始)2计算中间下标位置3比较中间下标位置的数组值与目标值的大......
  • 关于AT24C02的学习
    一、基本概念二、特性说明三、内存结构四、器件地址五、指令描述/************************************************************************************@filemain.c*@[email protected]*@versionV1*@date2024-11-13*@briefAT2......
  • 旺仔水饺-冲刺计划
    作业所属课程https://edu.cnblogs.com/campus/fzu/SE2024作业要求https://edu.cnblogs.com/campus/fzu/SE2024/homework/13305团队名称旺仔水饺102201140黎曼102201138黄俊瑶102201127罗永辉102201130郑哲浩102202144傅钰102202147赖越1722090......
  • 真题练习6-Excel电子表格-全国计算机等级考试二级MS Office高级应用与设计考试【汪老
    视频解析真题练习6-Excel电子表格_哔哩哔哩_bilibili题库下载全国计算机等级考试题库下载(用电脑下载安装):请点击题目要求某公司销售部门主管大华拟对本公司产品前两季度的销售情况进行统计,按下述要求帮助大华完成统计工作:1.在考生文件夹下,将“Excel素材.xlsx”文件另存为“......
  • 雷军:十年程序生涯
    无意间翻到了雷总早年的博客,写了自己程序员生涯的一些感悟,非常真实,分享给大家,以下是原文。最近,和UCWEB同事讨论,怎么才能把我们的UCWEB做到极致。我说,“手机上的平台非常多,如果想做好,需要足够多、足够优秀的程序员。优秀的程序员如何定义呢?首先必须热爱写程序,其次必须是一个完美主......
  • Qt | 串口调试工具实现
    点击上方"蓝字"关注我们01、QSerialPort>>>QSerialPort是Qt框架中的一个类,用于串行通信。它提供了一个简单的接口,允许开发者通过串口与外部设备(如传感器、相机、单片机等)进行数据交换。QSerialPort支持多种串口操作,可以方便地设置波特率、数据位、停止位和校验位等通......
  • The sol to pairing
    Thesoltopairinghttps://www.luogu.com.cn/problem/P11187思路把答案序列中相邻而相等的两个数,我们称之为“块”。那么可以发现,对于以某块为结尾的一个答案序列,其一定是由一个结尾不为该块的序列转移而来。因而,本题具有最优子结构性质,可以使用动态规划求解。\(1.\)对于......