欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python神經(jīng)網(wǎng)絡(luò)Keras?GhostNet模型的實(shí)現(xiàn)

 更新時(shí)間:2022年05月07日 16:15:21   作者:Bubbliiiing  
這篇文章主要為大家介紹了python神經(jīng)網(wǎng)絡(luò)Keras?GhostNet模型的復(fù)現(xiàn)詳解,

什么是GhostNet模型

GhostNet是華為諾亞方舟實(shí)驗(yàn)室提出來(lái)的一個(gè)非常有趣的網(wǎng)絡(luò),我們一起來(lái)學(xué)習(xí)一下。

2020年,華為新出了一個(gè)輕量級(jí)網(wǎng)絡(luò),命名為GhostNet。

在優(yōu)秀CNN模型中,特征圖存在冗余是非常重要的。如圖所示,這個(gè)是對(duì)ResNet-50第一個(gè)殘差塊特征圖進(jìn)行可視化的結(jié)果,當(dāng)我們給一個(gè)神經(jīng)網(wǎng)絡(luò)輸入一張圖片時(shí),我們可以獲得特別多的特征圖。

利用小扳手連接起來(lái)的兩幅特征圖,它們的相似性就特別高,這個(gè)就是神經(jīng)網(wǎng)絡(luò)中存在的特征圖冗雜的情況。

作者將相似的特征圖認(rèn)為是彼此的Ghost,所以這個(gè)網(wǎng)絡(luò)就叫做GhostNet(誤)。

在GhostNet這篇論文里面,作者認(rèn)為可以使用一些計(jì)算量更低(Cheap Operations)的操作去生成這些冗余的特征圖,這樣就可以在保證良好檢測(cè)效果的情況下,減少模型的參數(shù)量與提高模型的執(zhí)行速度。

源碼下載

GhostNet模型的實(shí)現(xiàn)思路

1、Ghost Module

通過(guò)上述的介紹,我們了解到了,GhostNet的核心思想就是使用一些計(jì)算量更低(Cheap Operations)的操作去生成這些冗余的特征圖。

在論文中,作者設(shè)計(jì)了一個(gè)名為Ghost Module的模塊,他的功能是代替普通卷積。

Ghost Module將普通卷積分為兩部分,首先進(jìn)行一個(gè)普通的1x1卷積,這是一個(gè)少量卷積,比如正常使用32通道的卷積,這里就用16通道的卷積,這個(gè)1x1卷積的作用類(lèi)似于特征整合,生成輸入特征層的特征濃縮。

然后我們?cè)龠M(jìn)行深度可分離卷積,這個(gè)深度可分離卷積是逐層卷積,它也就是我們上面提到的Cheap Operations。它利用上一步獲得的特征濃縮生成Ghost特征圖。

因此,如果我們從整體上去看這個(gè)Ghost Module,它其實(shí)就是兩步簡(jiǎn)單思想的匯總:

1、利用1x1卷積獲得輸入特征的必要特征濃縮。

2、利用深度可分離卷積獲得特征濃縮的相似特征圖(Ghost)。

Ghost Module的實(shí)現(xiàn)代碼如下:

def _ghost_module(inputs, exp, kernel, dw_kernel, ratio, strides=1,
                    padding='same',use_bias=False, relu=True):
    output_channels = math.ceil(exp * 1.0 / ratio)
    x = Conv2D(output_channels, kernel, strides=strides, padding=padding, use_bias=use_bias)(inputs)
    x = BatchNormalization()(x)
    if relu:
        x = Activation('relu')(x)
    dw = DepthwiseConv2D(dw_kernel, strides, padding=padding, depth_multiplier=ratio-1, use_bias=use_bias)(x)
    dw = BatchNormalization()(dw)
    if relu:
        dw = Activation('relu')(dw)
    x = Concatenate(axis=-1)([x,dw])
    x = Lambda(slices, arguments={'n':exp})(x)
    return x

2、Ghost Bottlenecks

Ghost Bottlenecks是由Ghost Module組成的瓶頸結(jié)構(gòu),就像這樣。

其實(shí)本質(zhì)上就是用Ghost Module,來(lái)代替瓶頸結(jié)構(gòu)里面的普通卷積。

Ghost Bottlenecks可以分為兩個(gè)部分,分別是主干部分和殘差邊部分,包含Ghost Module的,我們稱(chēng)它為主干部分。

Ghost Bottlenecks有兩個(gè)種類(lèi),如下圖所示,當(dāng)我們需要對(duì)特征層的寬高進(jìn)行壓縮的時(shí)候,我們會(huì)設(shè)置這個(gè)Ghost Bottlenecks的Stride=2,即步長(zhǎng)為2。

此時(shí)我們會(huì)Bottlenecks里面多添加一些卷積層,在主干部分里,我們會(huì)在兩個(gè)Ghost Module中添加一個(gè)步長(zhǎng)為2x2的深度可分離卷積進(jìn)行特征層的寬高壓縮。在殘差邊部分,我們也會(huì)添加上一個(gè)步長(zhǎng)為2x2的深度可分離卷積和1x1的普通卷積。

Ghost Bottlenecks的實(shí)現(xiàn)代碼如下:

def _ghost_bottleneck(inputs, output_channel, hidden_channel, kernel, ghost_kernel, strides, ratio, squeeze):
    input_shape = K.int_shape(inputs)       # 獲取輸入張量的尺寸
    x = _ghost_module(inputs, hidden_channel, [1,1], ghost_kernel, ratio)
    if strides > 1:
        x = DepthwiseConv2D(kernel, strides, padding='same', depth_multiplier=1, use_bias=False)(x)
        x = BatchNormalization()(x)
    if squeeze:
        x = _squeeze(x, hidden_channel, 4)
    x = _ghost_module(x, output_channel, [1,1], ghost_kernel, ratio, relu=False)
    if strides == 1 and input_shape[-1] == output_channel:
        res = inputs
    else:
        res = DepthwiseConv2D(kernel, strides=strides, padding='same', depth_multiplier=1, use_bias=False)(inputs)
        res = BatchNormalization()(res)
        res = Conv2D(output_channel, (1, 1), padding='same', strides=(1, 1), use_bias=False)(res)
        res = BatchNormalization()(res)
    x = Add()([res, x])
    return x

3、Ghostnet的構(gòu)建

整個(gè)Ghostnet的構(gòu)建方式如列表所示:

可以看到,整個(gè)Ghostnet都是由Ghost Bottlenecks進(jìn)行組成的。

當(dāng)一張圖片輸入到Ghostnet當(dāng)中時(shí),我們首先進(jìn)行一個(gè)16通道的普通1x1卷積塊(卷積+標(biāo)準(zhǔn)化+激活函數(shù))。

之后我們就開(kāi)始Ghost Bottlenecks的堆疊了,利用Ghost Bottlenecks,我們最終獲得了一個(gè)7x7x160的特征層(當(dāng)輸入是224x224x3的時(shí)候)。

然后我們會(huì)利用一個(gè)1x1的卷積塊進(jìn)行通道數(shù)的調(diào)整,此時(shí)我們可以獲得一個(gè)7x7x960的特征層。

之后我們進(jìn)行一次全局平均池化,然后再利用一個(gè)1x1的卷積塊進(jìn)行通道數(shù)的調(diào)整,獲得一個(gè)1x1x1280的特征層。

然后平鋪后進(jìn)行全連接就可以進(jìn)行分類(lèi)了。

GhostNet的代碼構(gòu)建

1、模型代碼的構(gòu)建

GhostNet的實(shí)現(xiàn)代碼如下,該代碼是Ghostnet在YoloV4上的應(yīng)用,可以參考一下:

import math
import warnings
import numpy as np
import tensorflow as tf
from keras import backend as K
from keras.applications.imagenet_utils import decode_predictions
from keras.initializers import random_normal
from keras.layers import (Activation, Add, BatchNormalization, Concatenate,
                          Conv2D, DepthwiseConv2D, GlobalAveragePooling2D, 
                          Lambda, Multiply, Reshape)
def slices(dw, n):
    return dw[:,:,:,:n]
def _make_divisible(v, divisor, min_value=None):
    if min_value is None:
        min_value = divisor
    new_v = max(min_value, int(v + divisor / 2) // divisor * divisor)
    if new_v < 0.9 * v:
        new_v += divisor
    return new_v
def _squeeze(inputs, hidden_channel, ratio, block_id, sub_block_id):
    x = GlobalAveragePooling2D()(inputs)
    x = Reshape((1,1,-1))(x)
    x = Conv2D(_make_divisible(hidden_channel/ratio, 4), (1,1), strides=(1,1), padding='same', kernel_initializer=random_normal(stddev=0.02),
            name="blocks."+str(block_id)+"."+str(sub_block_id)+".se.conv_reduce")(x)
    x = Activation('relu')(x)
    x = Conv2D(hidden_channel, (1,1),strides=(1,1), padding='same', kernel_initializer=random_normal(stddev=0.02),
            name="blocks."+str(block_id)+"."+str(sub_block_id)+".se.conv_expand")(x)
    x = Activation('hard_sigmoid')(x)
    x = Multiply()([inputs, x])    # inputs和x逐元素相乘
    return x
def _ghost_module(inputs, exp, ratio, block_id, sub_block_id, part, kernel_size=1, dw_size=3, stride=1, relu=True):
    output_channels = math.ceil(exp * 1.0 / ratio)
    x = Conv2D(output_channels, kernel_size, strides=stride, padding="same", use_bias=False, kernel_initializer=random_normal(stddev=0.02),
            name="blocks."+str(block_id)+"."+str(sub_block_id)+".ghost"+str(part)+".primary_conv.0")(inputs)
    x = BatchNormalization(name="blocks."+str(block_id)+"."+str(sub_block_id)+".ghost"+str(part)+".primary_conv.1")(x)
    if relu:
        x = Activation('relu')(x)
    dw = DepthwiseConv2D(dw_size, 1, padding="same", depth_multiplier=ratio-1, use_bias=False, depthwise_initializer=random_normal(stddev=0.02), 
            name="blocks."+str(block_id)+"."+str(sub_block_id)+".ghost"+str(part)+".cheap_operation.0")(x)
    dw = BatchNormalization(name="blocks."+str(block_id)+"."+str(sub_block_id)+".ghost"+str(part)+".cheap_operation.1")(dw)
    if relu:
        dw = Activation('relu')(dw)
    x = Concatenate(axis=-1)([x,dw])
    x = Lambda(slices, arguments={'n':exp})(x)
    return x
def _ghost_bottleneck(inputs, output_channel, hidden_channel, kernel, strides, ratio, squeeze, block_id, sub_block_id):
    input_shape = K.int_shape(inputs)
    x = _ghost_module(inputs, hidden_channel, ratio, block_id, sub_block_id, 1)
    if strides > 1:
        x = DepthwiseConv2D(kernel, strides, padding='same', depth_multiplier=1, use_bias=False, depthwise_initializer=random_normal(stddev=0.02),
                name="blocks."+str(block_id)+"."+str(sub_block_id)+".conv_dw")(x)
        x = BatchNormalization(name="blocks."+str(block_id)+"."+str(sub_block_id)+".bn_dw")(x)
    if squeeze:
        x = _squeeze(x, hidden_channel, 4, block_id, sub_block_id)
    x = _ghost_module(x, output_channel, ratio, block_id, sub_block_id, 2, relu=False)
    if strides == 1 and input_shape[-1] == output_channel:
        res = inputs
    else:
        res = DepthwiseConv2D(kernel, strides=strides, padding='same', depth_multiplier=1, use_bias=False, depthwise_initializer=random_normal(stddev=0.02),
                name="blocks."+str(block_id)+"."+str(sub_block_id)+".shortcut.0")(inputs)
        res = BatchNormalization(name="blocks."+str(block_id)+"."+str(sub_block_id)+".shortcut.1")(res)
        res = Conv2D(output_channel, (1, 1), padding='same', strides=(1, 1), use_bias=False, kernel_initializer=random_normal(stddev=0.02),
                name="blocks."+str(block_id)+"."+str(sub_block_id)+".shortcut.2")(res)
        res = BatchNormalization(name="blocks."+str(block_id)+"."+str(sub_block_id)+".shortcut.3")(res)
    x = Add()([res, x])
    return x
def Ghostnet(inputs):
    x = Conv2D(16, (3, 3), padding="same", strides=(2, 2), use_bias=False, kernel_initializer=random_normal(stddev=0.02), name="conv_stem")(inputs)
    x = BatchNormalization(name="bn1")(x)
    x = Activation('relu')(x)
    x = _ghost_bottleneck(x, 16, 16, (3, 3), strides=1, ratio=2, squeeze=False, block_id=0, sub_block_id=0)
    x = _ghost_bottleneck(x, 24, 48, (3, 3), strides=2, ratio=2, squeeze=False, block_id=1, sub_block_id=0)
    x = _ghost_bottleneck(x, 24, 72, (3, 3), strides=1, ratio=2, squeeze=False, block_id=2, sub_block_id=0)
    x = _ghost_bottleneck(x, 40, 72, (5, 5), strides=2, ratio=2, squeeze=True, block_id=3, sub_block_id=0)
    x = _ghost_bottleneck(x, 40, 120, (5, 5), strides=1, ratio=2, squeeze=True, block_id=4, sub_block_id=0)
    feat1 = x
    x = _ghost_bottleneck(x, 80, 240, (3, 3), strides=2, ratio=2, squeeze=False, block_id=5, sub_block_id=0)
    x = _ghost_bottleneck(x, 80, 200, (3, 3), strides=1, ratio=2, squeeze=False, block_id=6, sub_block_id=0)
    x = _ghost_bottleneck(x, 80, 184, (3, 3), strides=1, ratio=2, squeeze=False, block_id=6, sub_block_id=1)
    x = _ghost_bottleneck(x, 80, 184, (3, 3), strides=1, ratio=2, squeeze=False, block_id=6, sub_block_id=2)
    x = _ghost_bottleneck(x, 112, 480, (3, 3), strides=1, ratio=2, squeeze=True, block_id=6, sub_block_id=3)
    x = _ghost_bottleneck(x, 112, 672, (3, 3), strides=1, ratio=2, squeeze=True, block_id=6, sub_block_id=4)
    feat2 = x
    x = _ghost_bottleneck(x, 160, 672, (5, 5), strides=2, ratio=2, squeeze=True, block_id=7, sub_block_id=0)
    x = _ghost_bottleneck(x, 160, 960, (5, 5), strides=1, ratio=2, squeeze=False, block_id=8, sub_block_id=0)
    x = _ghost_bottleneck(x, 160, 960, (5, 5), strides=1, ratio=2, squeeze=True, block_id=8, sub_block_id=1)
    x = _ghost_bottleneck(x, 160, 960, (5, 5), strides=1, ratio=2, squeeze=False, block_id=8, sub_block_id=2)
    x = _ghost_bottleneck(x, 160, 960, (5, 5), strides=1, ratio=2, squeeze=True, block_id=8, sub_block_id=3)
    feat3 = x
    return feat1,feat2,feat3

2、Yolov4上的應(yīng)用

作為一個(gè)輕量級(jí)網(wǎng)絡(luò),我把Ghostnet和Mobilenet放在一起,作為Yolov4的主干網(wǎng)絡(luò)進(jìn)行特征提取。

對(duì)于yolov4來(lái)講,我們需要利用主干特征提取網(wǎng)絡(luò)獲得的三個(gè)有效特征進(jìn)行加強(qiáng)特征金字塔的構(gòu)建。

我們通過(guò)上述代碼可以取出三個(gè)有效特征層,我們可以利用這三個(gè)有效特征層替換原來(lái)yolov4主干網(wǎng)絡(luò)CSPdarknet53的有效特征層。

為了進(jìn)一步減少參數(shù)量,我們可以使用深度可分離卷積代替yoloV3中用到的普通卷積。

最終Ghostnet-Yolov4的構(gòu)建代碼如下:

from functools import wraps
from keras import backend as K
from keras.initializers import random_normal
from keras.layers import (Activation, BatchNormalization, Concatenate, Conv2D,
                          DepthwiseConv2D, Input, Lambda, MaxPooling2D,
                          UpSampling2D)
from keras.layers.normalization import BatchNormalization
from keras.models import Model
from keras.regularizers import l2
from utils.utils import compose
from nets.ghostnet import Ghostnet
from nets.mobilenet_v1 import MobileNetV1
from nets.mobilenet_v2 import MobileNetV2
from nets.mobilenet_v3 import MobileNetV3
from nets.yolo_training import yolo_loss
def relu6(x):
    return K.relu(x, max_value=6)
#------------------------------------------------------#
#   單次卷積DarknetConv2D
#   如果步長(zhǎng)為2則自己設(shè)定padding方式。
#------------------------------------------------------#
@wraps(Conv2D)
def DarknetConv2D(*args, **kwargs):
    darknet_conv_kwargs = {'kernel_initializer' : random_normal(stddev=0.02), 'kernel_regularizer': l2(5e-4)}
    darknet_conv_kwargs['padding'] = 'valid' if kwargs.get('strides')==(2,2) else 'same'
    darknet_conv_kwargs.update(kwargs)
    return Conv2D(*args, **darknet_conv_kwargs)
#---------------------------------------------------#
#   卷積塊 -> 卷積 + 標(biāo)準(zhǔn)化 + 激活函數(shù)
#   DarknetConv2D + BatchNormalization + Relu6
#---------------------------------------------------#
def DarknetConv2D_BN_Leaky(*args, **kwargs):
    no_bias_kwargs = {'use_bias': False}
    no_bias_kwargs.update(kwargs)
    return compose( 
        DarknetConv2D(*args, **no_bias_kwargs),
        BatchNormalization(),
        Activation(relu6))
#---------------------------------------------------#
#   深度可分離卷積塊
#   DepthwiseConv2D + BatchNormalization + Relu6
#---------------------------------------------------#
def _depthwise_conv_block(inputs, pointwise_conv_filters, alpha = 1,
                          depth_multiplier=1, strides=(1, 1)):
    pointwise_conv_filters = int(pointwise_conv_filters * alpha)
    x = DepthwiseConv2D((3, 3), depthwise_initializer=random_normal(stddev=0.02),
                        padding='same',
                        depth_multiplier=depth_multiplier,
                        strides=strides,
                        use_bias=False)(inputs)
    x = BatchNormalization()(x)
    x = Activation(relu6)(x)
    x = DarknetConv2D(pointwise_conv_filters, (1, 1), 
                    padding='same',
                    use_bias=False,
                    strides=(1, 1))(x)
    x = BatchNormalization()(x)
    return Activation(relu6)(x)
#---------------------------------------------------#
#   進(jìn)行五次卷積
#---------------------------------------------------#
def make_five_convs(x, num_filters):
    # 五次卷積
    x = DarknetConv2D_BN_Leaky(num_filters, (1,1))(x)
    x = _depthwise_conv_block(x, num_filters*2,alpha=1)
    x = DarknetConv2D_BN_Leaky(num_filters, (1,1))(x)
    x = _depthwise_conv_block(x, num_filters*2,alpha=1)
    x = DarknetConv2D_BN_Leaky(num_filters, (1,1))(x)
    return x
#---------------------------------------------------#
#   Panet網(wǎng)絡(luò)的構(gòu)建,并且獲得預(yù)測(cè)結(jié)果
#---------------------------------------------------#
def yolo_body(input_shape, anchors_mask, num_classes, backbone="mobilenetv1", alpha=1):
    inputs = Input(input_shape)
    #---------------------------------------------------#   
    #   生成mobilnet的主干模型,獲得三個(gè)有效特征層。
    #---------------------------------------------------#
    if backbone=="mobilenetv1":
        #---------------------------------------------------#   
        #   52,52,256;26,26,512;13,13,1024
        #---------------------------------------------------#
        feat1,feat2,feat3 = MobileNetV1(inputs, alpha=alpha)
    elif backbone=="mobilenetv2":
        #---------------------------------------------------#   
        #   52,52,32;26,26,92;13,13,320
        #---------------------------------------------------#
        feat1,feat2,feat3 = MobileNetV2(inputs, alpha=alpha)
    elif backbone=="mobilenetv3":
        #---------------------------------------------------#   
        #   52,52,40;26,26,112;13,13,160
        #---------------------------------------------------#
        feat1,feat2,feat3 = MobileNetV3(inputs, alpha=alpha)
    elif backbone=="ghostnet":
        #---------------------------------------------------#   
        #   52,52,40;26,26,112;13,13,160
        #---------------------------------------------------#
        feat1,feat2,feat3 = Ghostnet(inputs)
    else:
        raise ValueError('Unsupported backbone - `{}`, Use mobilenetv1, mobilenetv2, mobilenetv3, ghostnet.'.format(backbone))
    P5 = DarknetConv2D_BN_Leaky(int(512* alpha), (1,1))(feat3)
    P5 = _depthwise_conv_block(P5, int(1024* alpha))
    P5 = DarknetConv2D_BN_Leaky(int(512* alpha), (1,1))(P5)
    maxpool1 = MaxPooling2D(pool_size=(13,13), strides=(1,1), padding='same')(P5)
    maxpool2 = MaxPooling2D(pool_size=(9,9), strides=(1,1), padding='same')(P5)
    maxpool3 = MaxPooling2D(pool_size=(5,5), strides=(1,1), padding='same')(P5)
    P5 = Concatenate()([maxpool1, maxpool2, maxpool3, P5])
    P5 = DarknetConv2D_BN_Leaky(int(512* alpha), (1,1))(P5)
    P5 = _depthwise_conv_block(P5, int(1024* alpha))
    P5 = DarknetConv2D_BN_Leaky(int(512* alpha), (1,1))(P5)
    P5_upsample = compose(DarknetConv2D_BN_Leaky(int(256* alpha), (1,1)), UpSampling2D(2))(P5)
    P4 = DarknetConv2D_BN_Leaky(int(256* alpha), (1,1))(feat2)
    P4 = Concatenate()([P4, P5_upsample])
    P4 = make_five_convs(P4,int(256* alpha))
    P4_upsample = compose(DarknetConv2D_BN_Leaky(int(128* alpha), (1,1)), UpSampling2D(2))(P4)
    P3 = DarknetConv2D_BN_Leaky(int(128* alpha), (1,1))(feat1)
    P3 = Concatenate()([P3, P4_upsample])
    P3 = make_five_convs(P3,int(128* alpha))
    #---------------------------------------------------#
    #   第三個(gè)特征層
    #   y3=(batch_size,52,52,3,85)
    #---------------------------------------------------#
    P3_output = _depthwise_conv_block(P3, int(256* alpha))
    P3_output = DarknetConv2D(len(anchors_mask[0])*(num_classes+5), (1,1))(P3_output)
    P3_downsample = _depthwise_conv_block(P3, int(256* alpha), strides=(2,2))
    P4 = Concatenate()([P3_downsample, P4])
    P4 = make_five_convs(P4,int(256* alpha))
    #---------------------------------------------------#
    #   第二個(gè)特征層
    #   y2=(batch_size,26,26,3,85)
    #---------------------------------------------------#
    P4_output = _depthwise_conv_block(P4, int(512* alpha))
    P4_output = DarknetConv2D(len(anchors_mask[1])*(num_classes+5), (1,1))(P4_output)
    P4_downsample = _depthwise_conv_block(P4, int(512* alpha), strides=(2,2))
    P5 = Concatenate()([P4_downsample, P5])
    P5 = make_five_convs(P5,int(512* alpha))
    #---------------------------------------------------#
    #   第一個(gè)特征層
    #   y1=(batch_size,13,13,3,85)
    #---------------------------------------------------#
    P5_output = _depthwise_conv_block(P5, int(1024* alpha))
    P5_output = DarknetConv2D(len(anchors_mask[2])*(num_classes+5), (1,1))(P5_output)
    return Model(inputs, [P5_output, P4_output, P3_output])

以上就是python神經(jīng)網(wǎng)絡(luò)Keras GhostNet模型的復(fù)現(xiàn)詳解的詳細(xì)內(nèi)容,更多關(guān)于Keras GhostNet模型復(fù)現(xiàn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • python 實(shí)現(xiàn)圖片旋轉(zhuǎn) 上下左右 180度旋轉(zhuǎn)的示例

    python 實(shí)現(xiàn)圖片旋轉(zhuǎn) 上下左右 180度旋轉(zhuǎn)的示例

    今天小編就為大家分享一篇python 實(shí)現(xiàn)圖片旋轉(zhuǎn) 上下左右 180度旋轉(zhuǎn)的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • python語(yǔ)言中with as的用法使用詳解

    python語(yǔ)言中with as的用法使用詳解

    本篇文章主要介紹了python語(yǔ)言中with as的用法使用詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • Python 函數(shù)用法簡(jiǎn)單示例【定義、參數(shù)、返回值、函數(shù)嵌套】

    Python 函數(shù)用法簡(jiǎn)單示例【定義、參數(shù)、返回值、函數(shù)嵌套】

    這篇文章主要介紹了Python 函數(shù)用法,結(jié)合實(shí)例形式分析了Python函數(shù)定義、參數(shù)、返回值及函數(shù)嵌套相關(guān)使用技巧,需要的朋友可以參考下
    2019-09-09
  • Django 創(chuàng)建新App及其常用命令的實(shí)現(xiàn)方法

    Django 創(chuàng)建新App及其常用命令的實(shí)現(xiàn)方法

    這篇文章主要介紹了Django 創(chuàng)建新App及其常用命令的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Python?OpenCV實(shí)現(xiàn)圖像增強(qiáng)操作詳解

    Python?OpenCV實(shí)現(xiàn)圖像增強(qiáng)操作詳解

    由于很多不確定因素,導(dǎo)致圖像采集的光環(huán)境極其復(fù)雜;為了提高目標(biāo)檢測(cè)模型的泛化能力,本文將使用python中的opencv模塊實(shí)現(xiàn)常見(jiàn)的圖像增強(qiáng)方法,感興趣的可以了解一下
    2022-10-10
  • Python OpenCV實(shí)現(xiàn)裁剪并保存圖片

    Python OpenCV實(shí)現(xiàn)裁剪并保存圖片

    這篇文章主要為大家詳細(xì)介紹了Python OpenCV實(shí)現(xiàn)裁剪并保存圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • django的安裝和創(chuàng)建應(yīng)用過(guò)程詳解

    django的安裝和創(chuàng)建應(yīng)用過(guò)程詳解

    這篇文章主要介紹了django的安裝和創(chuàng)建應(yīng)用,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • Python queue模塊攻略全解

    Python queue模塊攻略全解

    這篇文章主要為大家介紹了Python queue模塊攻略全解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • python鏈接Oracle數(shù)據(jù)庫(kù)的方法

    python鏈接Oracle數(shù)據(jù)庫(kù)的方法

    這篇文章主要介紹了python鏈接Oracle數(shù)據(jù)庫(kù)的方法,實(shí)例分析了Python使用cx_Oracle模塊操作Oracle數(shù)據(jù)庫(kù)的相關(guān)技巧,需要的朋友可以參考下
    2015-06-06
  • Webots下載安裝?+?Pycharm聯(lián)調(diào)使用教程

    Webots下載安裝?+?Pycharm聯(lián)調(diào)使用教程

    Webots是一個(gè)開(kāi)源的三維移動(dòng)機(jī)器人模擬器,它最初是作為研究移動(dòng)機(jī)器人中各種控制算法的研究工具開(kāi)發(fā)的,自2018年12月起,Webots作為開(kāi)源軟件發(fā)布,并獲得Apache 2.0許可證,這篇文章主要介紹了Webots下載安裝?+?Pycharm聯(lián)調(diào)?,需要的朋友可以參考下
    2023-02-02

最新評(píng)論