文章目录

  • utils.py 文件的理解:一些小脚本文件
    • 1. 包含的函数
    • 1.1. def to_cpu(tensor):
    • 1.2. def load_classes(path): 加载数据集的类别
    • 1.3. def weights_init_normal(m): 权重初始化
    • 这里还要写一个文档来理解 self.children 的使用方法.
    • 1.4. def rescale_boxes(boxes, current_dim, original_shape): 将相对网络输入的box转化成原始图片的box
    • 1.5. def xywh2xyxy(x):
    • 1.6. def ap_per_class(tp, conf, pred_cls, target_cls): 不懂
    • 1.7. def compute_ap(recall, precision): 不懂
    • 1.8. def get_batch_statistics(outputs, targets, iou_threshold): 评估一个 batch 中多张图片的检测结果
    • 1.9. def bbox_wh_iou(wh1, wh2): # 求 box 与 anchor 的交并比
    • 1.10. def bbox_iou(box1, box2, x1y1x2y2=True): 计算两个点坐标的box的交并比
    • 1. 11. def non_max_suppression(prediction, conf_thres=0.5, nms_thres=0.4): # 非极大抑制
      • 1. 代码如下:
      • 2. 理解如下:
        • 输入:
        • 输出:边框置信度 类别置信度 类别index
        • 函数算法:
    • 1.12. def build_targets(pred_boxes, pred_cls, target, anchors, ignore_thres): 看不懂
    • end

utils.py 文件的理解:一些小脚本文件

1. 包含的函数

1.1. def to_cpu(tensor):

  1. 代码如下:
def to_cpu(tensor):  # 张量 转移到 cpureturn tensor.detach().cpu()  # .detach() 创建成一个没有梯度的tensor, 如果想要保留梯度就使用tensor.clone()
  1. 理解如下:
    输入GPU上的 tensor ,
    返回GPU上的 tensor

1.2. def load_classes(path): 加载数据集的类别

  1. 代码如下:
def load_classes(path):  # 读取路径中文件成 列表 data/coco.names"""Loads class labels at 'path'"""fp = open(path, "r")names = fp.read().split("\n")[:-1]  # 读取coco数据集的名称,按行读取,每次只取每一行的最后一个return names  # 返回的是 coco name 类别名称的列表 list
  1. 理解如下:
    输入:包含数据集名称的文件路径,如:data/coco.names
    data/coco.names 的内容(打开像一个文本文档)如下:
person
bicycle
car
…… # 一共80行,coco 数据集有80类别

输出:

['person', 'bicycle', 'car', 'motorbike', ……]

1.3. def weights_init_normal(m): 权重初始化

  1. 代码如下:
def weights_init_normal(m):  # 自定义初始化权重的函数# m 是网络中的(每)一个submodule(子模块),这weights_init_normal函数被调用来初始化模型中每一个子模块的参数。# model.apply(fn) 的作用是 将 fn function to be applied to each submoduleclassname = m.__class__.__name__if classname.find("Conv") != -1:  # 这里等于 -1 表示,torch.nn.init.normal_(m.weight.data, 0.0, 0.02)  # 将正太分布N(0, 0.2)生成的值赋值给 m.weight.data 中的每个元素elif classname.find("BatchNorm2d") != -1:torch.nn.init.normal_(m.weight.data, 1.0, 0.02)torch.nn.init.constant_(m.bias.data, 0.0)  # 将 0 赋值给 m.bias.data
  1. 理解如下:

这里定义的这个 weights_init_normal 函数会作为 model.apply(fn)的输入fn。即 fn 是函数weights_init_normal。

函数在 train.py 中被使用,使用如下

model.apply(weights_init_normal)   # train.py 中模型初始化参数

model 的 apply 函数是torch中 Module(object) 类中的一个标准函数。
torch 中 model.apply 定义如下

class Module(object):def apply(self, fn):for module in self.children():module.apply(fn)  # 这是一个递归fn(self)  # 这里的fn 就是 我们定义的 def weights_init_normal(m) 初始化权重函数return self

这里还要写一个文档来理解 self.children 的使用方法.

1.4. def rescale_boxes(boxes, current_dim, original_shape): 将相对网络输入的box转化成原始图片的box

  1. 代码如下:
def rescale_boxes(boxes, current_dim, original_shape):  # 将相对网络输入的box转化成原始图片的box。""" Rescales bounding boxes to the original shape现在的 boxes: 是输入神经网络中的图片的 boxes, 不是原始图片的 boxes ,所以需要将 boxes 转换成原始图片的 boxes。current_dim: 通常是 416original_shape: coco数据集中的原始图片的 shape 各不相同"""orig_h, orig_w = original_shape# The amount of padding that was addedpad_x = max(orig_h - orig_w, 0) * (current_dim / max(original_shape))  # 水平上 左右 pad 的和pad_y = max(orig_w - orig_h, 0) * (current_dim / max(original_shape))  # 垂直上 上下 pad 的和# Image height and width after padding is removedunpad_h = current_dim - pad_yunpad_w = current_dim - pad_x# Rescale bounding boxes to dimension of original imageboxes[:, 0] = ((boxes[:, 0] - pad_x // 2) / unpad_w) * orig_wboxes[:, 1] = ((boxes[:, 1] - pad_y // 2) / unpad_h) * orig_hboxes[:, 2] = ((boxes[:, 2] - pad_x // 2) / unpad_w) * orig_wboxes[:, 3] = ((boxes[:, 3] - pad_y // 2) / unpad_h) * orig_hreturn boxes
  1. 理解如下:
    输入:
    boxes:是 yolo(相对于current_dim) 的检测结果,是一个列表,存放过的是box左上角和右下角两个点的四个坐标值: xyxy 。
    current_dim:当前图片的宽度或高度,416(下图中用黄色的小正方形表示)
    original_shape:h=1920, w=1080(下图中用蓝色额大矩形表示)
    返回:
    相对于输入图片的boxes 的坐标xyxy(一个box 用左上角和右下角的坐标来标志)

1.5. def xywh2xyxy(x):

  1. 代码如下:
def xywh2xyxy(x):  # 将中心坐标和高宽,转成左上角右下角的坐标y = x.new(x.shape)  # 创建一个新的空间y[..., 0] = x[..., 0] - x[..., 2] / 2y[..., 1] = x[..., 1] - x[..., 3] / 2y[..., 2] = x[..., 0] + x[..., 2] / 2y[..., 3] = x[..., 1] + x[..., 3] / 2return y
  1. 理解如下:
    输入:列表,四个值分别是 中心点的坐标xy, box 的宽度和高度
    输入:列表,四个值分别是 左上角的坐标,右下角的坐标。

1.6. def ap_per_class(tp, conf, pred_cls, target_cls): 不懂

""" Compute the average precision, given the recall and precision curves.Source: https://github.com/rafaelpadilla/Object-Detection-Metrics.# Argumentstp:    True positives (list).conf:  Objectness value from 0-1 (list).pred_cls: Predicted object classes (list).target_cls: True object classes (list).# ReturnsThe average precision as computed in py-faster-rcnn."""

1.7. def compute_ap(recall, precision): 不懂

   """ Compute the average precision, given the recall and precision curves.Code originally from https://github.com/rbgirshick/py-faster-rcnn.# Argumentsrecall:    The recall curve (list).precision: The precision curve (list).# ReturnsThe average precision as computed in py-faster-rcnn."""

1.8. def get_batch_statistics(outputs, targets, iou_threshold): 评估一个 batch 中多张图片的检测结果

  1. 代码如下:
  2. 理解如下
    2.1. 输入:
    outputs: 一个 batch 的图片的检测结果
    output = outputs[i]: 所有预测图片中编号为 i 的检测结果。一个 batch 中第 i 张图片的检测结果,含多个box,每一个box 有坐标(四个数据),概率,类别编号
    annotations = targets[targets[:, 0] == sample_i][:, 1:]
    targets: GT
    iou_threshold: 判断为 true 的最低交并比要求
    2.2. 输出:
    2.3. 过程:
    2.3.1 按一个 batch 中图片的编号遍历检测结果,将第 i 张图片的检测结果存入 output(一张图片的box)
    2.3.2. 从 targets 中找到那个图片编号同样是 i 的GT,作为 annotations(一张图片的box)
    2.3.3. 遍历一张图片output 中的每一个 box, 将这个box 与 annotations 中的每一个框计算交并比

1.9. def bbox_wh_iou(wh1, wh2): # 求 box 与 anchor 的交并比

  1. 代码如下:
def bbox_wh_iou(wh1, wh2):  # 求两个 box 的交并比wh2 = wh2.t()  # 转换数据的格式,并没有交换数据的位置w1, h1 = wh1[0], wh1[1]w2, h2 = wh2[0], wh2[1]inter_area = torch.min(w1, w2) * torch.min(h1, h2)  # 宽高都取最下的那个union_area = (w1 * h1 + 1e-16) + w2 * h2 - inter_areareturn inter_area / union_area
  1. 理解如下:
    输入的 wh1 和 wh2 都是yolo格式的坐标,即比例坐标。这里的两个 box 是wh 不相同,但他们两的中心点的坐标是相同的,所以计算交并比的时候,只需要计算w h的数据,比需要中心点的坐标数据。

1.10. def bbox_iou(box1, box2, x1y1x2y2=True): 计算两个点坐标的box的交并比


def bbox_iou(box1, box2, x1y1x2y2=True):"""Returns the IoU of two bounding boxes"""if not x1y1x2y2: 将 xywh的表示方式转换成 xyxy的表示方式# Transform from center and width to exact coordinatesb1_x1, b1_x2 = box1[:, 0] - box1[:, 2] / 2, box1[:, 0] + box1[:, 2] / 2b1_y1, b1_y2 = box1[:, 1] - box1[:, 3] / 2, box1[:, 1] + box1[:, 3] / 2b2_x1, b2_x2 = box2[:, 0] - box2[:, 2] / 2, box2[:, 0] + box2[:, 2] / 2b2_y1, b2_y2 = box2[:, 1] - box2[:, 3] / 2, box2[:, 1] + box2[:, 3] / 2else:# Get the coordinates of bounding boxesb1_x1, b1_y1, b1_x2, b1_y2 = box1[:, 0], box1[:, 1], box1[:, 2], box1[:, 3]b2_x1, b2_y1, b2_x2, b2_y2 = box2[:, 0], box2[:, 1], box2[:, 2], box2[:, 3]# get the corrdinates of the intersection rectangleinter_rect_x1 = torch.max(b1_x1, b2_x1)inter_rect_y1 = torch.max(b1_y1, b2_y1)inter_rect_x2 = torch.min(b1_x2, b2_x2)inter_rect_y2 = torch.min(b1_y2, b2_y2)# Intersection area  # torch.clamp 截断处理,将小于min的值取值为mininter_area = torch.clamp(inter_rect_x2 - inter_rect_x1 + 1, min=0) * torch.clamp(inter_rect_y2 - inter_rect_y1 + 1, min=0)# Union Areab1_area = (b1_x2 - b1_x1 + 1) * (b1_y2 - b1_y1 + 1)  # + 1 是因为边界宽度有个 1 ,注意这个点。b2_area = (b2_x2 - b2_x1 + 1) * (b2_y2 - b2_y1 + 1)iou = inter_area / (b1_area + b2_area - inter_area + 1e-16)return iou
  1. 理解如下:
    求交并比的重点:
    无论两个矩形框的表示形式是怎样的,都要转化成左上角右下角 xyxy 的格式。
    求左边界和上边界用 max
    求右边界和下边界用 min
    相交的宽度为负时,赋值为 0
    box 的宽度等于 右坐标 - 左坐标 + 1

1. 11. def non_max_suppression(prediction, conf_thres=0.5, nms_thres=0.4): # 非极大抑制

1. 代码如下:

def non_max_suppression(prediction, conf_thres=0.5, nms_thres=0.4):  # 非极大抑制"""Removes detections with lower object confidence score than 'conf_thres' and performsNon-Maximum Suppression to further filter detections.Returns detections with shape:(x1, y1, x2, y2, object_conf, class_score, class_pred)"""# From (center x, center y, width, height) to (x1, y1, x2, y2)prediction[..., :4] = xywh2xyxy(prediction[..., :4])  # 处理一个batch 每一张图片每一个对象的数据:坐标转换(只改变每一张图片的每一个预测框中的前四个坐标值,其他值不变)
#    prediction =  tensor([[
#         [1.2897e+01, 1.8118e+01, 1.7194e+02,  ..., 1.1081e-02,5.1385e-03, 3.2795e-03],
#         [5.7479e+01, 2.5666e+01, 1.1065e+02,  ..., 6.1178e-03,3.3721e-03, 9.3959e-04],
#         [7.7897e+01, 2.4972e+01, 1.4381e+02,  ..., 1.4635e-03,3.0854e-03, 8.7795e-04],
#         ...,
#         [3.9590e+02, 4.1341e+02, 7.7788e+01,  ..., 3.0758e-04, 1.1135e-04, 1.2358e-04],
#         [4.0272e+02, 4.1227e+02, 4.9530e+01,  ..., 3.6771e-04, 3.1682e-04, 4.5721e-04],
#         [4.1132e+02, 4.1317e+02, 7.5396e+01,  ..., 1.0301e-03, 9.6391e-04, 1.7760e-03]]])output = [None for _ in range(len(prediction))]  # 图片的长度for image_i, image_pred in enumerate(prediction):  # 遍历一张图片的每一个预测框(这里处理的对象是一张图片)# Filter out confidence scores below thresholdimage_pred = image_pred[image_pred[:, 4] >= conf_thres]  # 过滤掉 边框置信度小于阈值的框。0123是坐标,4是置信度,5:是种类# If none are remaining => process next imageif not image_pred.size(0):  # 如果 没有满足阈值要求的框,就访问下一个框continue# Object confidence times class confidencescore = image_pred[:, 4] * image_pred[:, 5:].max(1)[0]  # 求当前预测框类别中的极大值([0])。 在1方向(max(1)),找到每行(属于80个种类中的某一类的最大值)的最大值。#  框的位置执行度 * 框中对象的执行度(找的是每一个框的这个最大值,这里的每一行就是每一个框)# Sort by itimage_pred = image_pred[(-score).argsort()]  # .argsort() 返回从大到小排序索引值 (.argsort 是从小到大排序,加了符号之后就是从大到小的排序。)
# image_pred =  tensor([
#        [6.9979e+01, 1.7314e+02, 1.7263e+02, 3.4342e+02, 9.9952e-01, 2.7360e-06,
#         3.1124e-05, 7.5148e-08, 2.1126e-07, 7.7389e-09, 2.3194e-08, 5.6478e-10,
#         3.2973e-08, 4.0248e-07, 9.3334e-09, 9.8726e-08, 1.9962e-08, 1.4138e-08,
#         4.4086e-07, 1.7810e-05, 3.2029e-03, 9.9335e-01, 1.4822e-06, 1.3331e-05,
#         2.8374e-06, 2.3131e-07, 3.8589e-06, 6.9625e-08, 1.2171e-06, 3.3805e-06,
#         1.5626e-07, 9.1728e-08, 8.7323e-08, 1.3251e-07, 1.4588e-06, 2.2201e-06,
#         7.4246e-08, 1.9406e-07, 1.9214e-07, 1.8509e-08, 9.3417e-08, 2.9386e-06,
#         2.2876e-07, 2.0008e-07, 1.7397e-08, 1.9292e-09, 9.9117e-09, 1.0033e-09,
#         1.1846e-08, 4.8930e-08, 1.7767e-09, 2.1066e-07, 1.0837e-07, 1.8093e-07,
#         2.0299e-09, 4.5130e-07, 2.2242e-09, 1.1962e-07, 2.4569e-05, 2.8944e-07,
#         3.8133e-08, 1.9768e-07, 5.1894e-07, 1.6013e-06, 5.0550e-06, 6.7384e-08,
#         3.8338e-08, 1.3275e-07, 2.6257e-08, 3.8255e-08, 2.3908e-08, 1.3826e-07,
#         2.6799e-09, 3.1228e-08, 6.6355e-08, 2.0321e-08, 4.7900e-07, 1.1243e-08,
#         1.9466e-08, 2.2574e-07, 5.0917e-10, 2.6649e-08, 7.6042e-07, 7.5514e-08,
#         1.9578e-08],
#         [……],
#         [……],
#         ……])class_confs, class_preds = image_pred[:, 5:].max(1, keepdim=True)  # 返回每一行指定位置(5:)的最大值,和最大值的索引(类别取得最大值的索引就是类别编号)
# class_confs, class_preds =
# tensor([[0.9933],
#        [0.9998],
#        [0.9996],
#        [0.9880],
#        [0.9423],
#        [0.9894],
#        [0.9210],
#        [0.9850],
#        [0.9857]])
# tensor([[16],
#        [ 1],
#        [ 1],
#        [16],
#        [ 7],
#        [16],
#        [ 7],
#        [16],
#        [16]])
#detections = torch.cat((image_pred[:, :5], class_confs.float(), class_preds.float()), 1)  # 提取出 80个类别中class_confs最大的那一个,及其下标 class_preds;其他大的79个类别就不保留了# .cat 是将数据按行拼接起来。01234(image_pred[:, :5])表示4个坐标和1个框置信度,5(class_confs)表示类别置信度,6(class_preds)表示类别编号
# detections =  tensor([
#        [ 69.9790, 173.1447, 172.6293, 343.4247,   0.9995,   0.9933,  16.0000],
#        [ 92.8356, 111.2542, 305.3051, 294.4642,   0.9927,   0.9998,   1.0000],
#        [ 63.1184, 116.6243, 311.2260, 294.3138,   0.9900,   0.9996,   1.0000],
#        [ 68.8240, 157.3179, 172.9849, 340.8053,   0.9996,   0.9880,  16.0000],
#        [254.1283,  98.5848, 373.9042, 144.4332,   0.9970,   0.9423,   7.0000],
#        [ 70.7442, 184.7154, 168.4275, 335.5417,   0.9453,   0.9894,  16.0000],
#        [253.6593,  95.9781, 372.7262, 144.6945,   0.9973,   0.9210,   7.0000],
#        [ 70.6210, 173.2062, 169.2387, 327.5236,   0.9228,   0.9850,  16.0000],
#        [ 72.2745, 174.2344, 167.7682, 325.6776,   0.8158,   0.9857,  16.0000]])# Perform non-maximum suppressionkeep_boxes = []while detections.size(0):# detections[0, :4].unsqueeze(0)是 tensor([[ 69.9790, 173.1447, 172.6293, 343.4247]])large_overlap = bbox_iou(detections[0, :4].unsqueeze(0), detections[:, :4]) > nms_thres  # 计算出每一个box 与box[0] 交并比# detections[0, :4]:第一个检测对象(框)的四个坐标;.unsqueeze(0) 是为了增加一个维度,方便后面的计算# detections[:, :4]:图片中的每一个检测对象的四个坐标label_match = detections[0, -1] == detections[:, -1]  # 判断每一个 box 的类别与 box[0]的类别# label_match 是 tensor([1, 0, 0, 1, 0, 1, 0, 1, 1], dtype=torch.uint8)# Indices of boxes with lower confidence scores, large IOUs and matching labelsinvalid = large_overlap & label_match  # 将的得到的两个列表求与,box中与box[0] 同时满足IOU和类别 box#  invalid =  tensor([1, 0, 0, 1, 0, 1, 0, 1, 1], dtype=torch.uint8)# invalid 是 tensor([1, 0, 0, 1, 0, 1, 0, 1, 1], dtype=torch.uint8)# 表示下标为 3 5 7 8 的box与下标为0 的box 具有相同的类别且满足交并比要求weights = detections[invalid, 4:5]  # 将box 的置信度当成box 的 weights(可靠性、正确的程度)使用# weights =  tensor([[0.9995], [0.9996], [0.9453], [0.9228], [0.8158]])# Merge overlapping bboxes by order of confidencedetections[0, :4] = (weights * detections[invalid, :4]).sum(0) / weights.sum()  # 根据每一个box 的权重,进行加权求平均坐标
# detections =
#tensor([[ 70.4133, 172.3040, 170.3421, 335.0493,   0.9995,   0.9933,  16.0000],
#        [ 92.8356, 111.2542, 305.3051, 294.4642,   0.9927,   0.9998,   1.0000],
#        [ 63.1184, 116.6243, 311.2260, 294.3138,   0.9900,   0.9996,   1.0000],
#        [ 68.8240, 157.3179, 172.9849, 340.8053,   0.9996,   0.9880,  16.0000],
#        [254.1283,  98.5848, 373.9042, 144.4332,   0.9970,   0.9423,   7.0000],
#        [ 70.7442, 184.7154, 168.4275, 335.5417,   0.9453,   0.9894,  16.0000],
#        [253.6593,  95.9781, 372.7262, 144.6945,   0.9973,   0.9210,   7.0000],
#        [ 70.6210, 173.2062, 169.2387, 327.5236,   0.9228,   0.9850,  16.0000],
#        [ 72.2745, 174.2344, 167.7682, 325.6776,   0.8158,   0.9857,  16.0000]])keep_boxes += [detections[0]]  # 访问刚才生成的box, 将其(这个目标 box)添加到 keep_boxes 中。最终这个keep_boxes 会存放所有需要的box框# keep_boxes =  [tensor([ 70.4133, 172.3040, 170.3421, 335.0493,   0.9995,   0.9933,  16.0000])]detections = detections[~invalid]  # invalid 是一个列表,表示与box[0]重叠的目标,形如[1, 0, 0, 1, 1,0],#  这里取反再赋值就是 将detectioins 的值更新为 刚才没有分析过的 box, 对没有分析过的box 继续查找重叠,加权合并重叠。# 直到 detections 中没有任何 box
# detections =  tensor([[ 92.8356, 111.2542, 305.3051, 294.4642,   0.9927,   0.9998,   1.0000],
#        [ 63.1184, 116.6243, 311.2260, 294.3138,   0.9900,   0.9996,   1.0000],
#        [254.1283,  98.5848, 373.9042, 144.4332,   0.9970,   0.9423,   7.0000],
#        [253.6593,  95.9781, 372.7262, 144.6945,   0.9973,   0.9210,   7.0000]])if keep_boxes:output[image_i] = torch.stack(keep_boxes)  # 将一张图片的检测结果 keep_boxes (多个box)打包作为一张图片的检测结果。# output[image_i] 一张图片的加测结果return output  # 多张图片的检测结果

2. 理解如下:

输入:

prediction: 存放的是多个图片的检测结果,每张图片检测到多个目标框,每个目标框有多个值,依次是x y w h 边框置信度 80个类别的置信度。[[120 120 15 15 0.8 0.1 0.2 0.3……], [……], [……]],这里要理解成每一box边框只有一个边框置信度,当有80个类别置信度,最后的置信度这两个置信度的乘积。
conf_thres: 置信度阈值,是边框置信度和类别置信度的乘积。
nms_thres: 交并比阈值,合并相同类别的box时,同时需要满足的最低的交并比要求。

输出:边框置信度 类别置信度 类别index

函数算法:

  1. 遍历多张图片中的一张图片的检测结果
  2. 计算这一张图片中,每个box 的置信度(边框置信度 乘以 80个类别的置信度),只保留使得置信度最大的那个类别,将所有的box 按照置信度降序排。(每个box 只保留使置信度最大的类别,都不用考虑阈值参数)这样就可以得到 每一个box 的最大的那个置信度和 类别
  3. 每个box 只保留使得置信度最大的 边框执行度和类别执行度,以及类别index
  4. 对所有的目标box进行遍历,找到所有类别相同且满足IOU的这列框,对这些框进行加权 merge ,加权合并的框当做最后的框输出。这样就找到了该图片的所有输出框了。

1.12. def build_targets(pred_boxes, pred_cls, target, anchors, ignore_thres): 看不懂

end

utils.py 文件的理解:一些小脚本文件相关推荐

  1. mysql执行文件脚本文件_MySQL执行外部sql脚本文件的命令

    sql脚本是包含一到多个sql命令的sql语句,我们可以将这些sql脚本放在一个文本文件中(我们称之为"sql脚本文件"),然后通过相关的命令执行这个sql脚本文件.基本步骤如下: ...

  2. linux执行脚本提示文件忙,linux定时执行脚本文件fgo 封号吗

    当我们要移动控制项(Control)或表单(Form)时,很多人习惯这样写: frmCustomer.Left=frmCustomer.Left 100 frmCustomer.Top=frmCust ...

  3. Python小技巧:将大音频文件无损切割为小音频文件

    安装librosa.pydub两个音频处理包 . 少数闲话,多些代码: 将音频文件切割为10s的小音频文件,如下代码: ​from pydub import AudioSegment import p ...

  4. 中有冒号 文件路径_用Matlab脚本文件实现Excel文件的合并

    日常吐槽 前段时间跟同事聊天,同事洗脑了一个新的(扎心的)世界观,"人生分三个阶段,20岁时承认父母很平庸,30岁时承认自己很平庸,40岁时承认孩子很平庸".这是这位同事在孩子学而 ...

  5. 如何运行脚本文件linux,linux如何执行脚本文件逆水寒

    FSO通过CreateTextFile.OpenTextFile.OpenAsTextStream三种方法来创建一个顺序文本文件 搭建ssm框架首先我们需要有一个数据库,本篇文章博主将使用一个MySQ ...

  6. matlab中结束脚本运行_一个处理dump文件的小脚本

    各位看官可以考虑关注下我的公众号:LAMMPS 爱好者 同时安利下我们物美价廉的0基础入门培训班,有兴趣的同学可以进公众号了解~ 注:本文由深圳先进研究院梁挺博士原创 今天给大家介绍一个我在处理 la ...

  7. python用电度数设计_用Python实现一个爬取XX大学电费通知的小脚本

    内容简要 1分析网站 2简单爬取 3进阶自定义爬取 4保存进数据库 学校基础设施太差,宿舍电量过低提醒虽然贴在楼下,但是作为低头一族,经常忘记看提醒导致宿舍酣战时突然黑屏,为了避免这种尴尬的场景以及强 ...

  8. python 爬网页通知_用Python实现一个爬取XX大学电费通知的小脚本

    内容简要 1分析网站 2简单爬取 3进阶自定义爬取 4保存进数据库 学校基础设施太差,宿舍电量过低提醒虽然贴在楼下,但是作为低头一族,经常忘记看提醒导致宿舍酣战时突然黑屏,为了避免这种尴尬的场景以及强 ...

  9. php linux脚本文件,Unix/Linux中如何直接执行PHP脚本文件?

    使用Linux系统的服务器都有搭建完整的PHP环境,因此有些用户会用PHP去写一些执行自动化任务的脚本,可是发现每次执行PHP脚本都需要使用php myscript.php的方式,感觉有点麻烦.其实我 ...

最新文章

  1. [祝]微软山西DotNet俱乐部(高校行系列)山西大学公益讲座
  2. 《数字城堡》大片制作
  3. 2014-06-25nbsp;12:55
  4. Google提出的新型激活函数:Swish
  5. ubuntu 终端内查找/搜索
  6. 制作程序化装饰花纹图案_装饰图案
  7. CSS中class优先级问题
  8. Educational Codeforces Round 41 (Rated for Div. 2)
  9. ThinkJS框架入门详细教程(二)新手入门项目
  10. 聚类算法实践——PCCA、SOM、Affinity Propagation
  11. 2021-06-16 forkjion stream流式计算方法
  12. keil5安装教程及下载
  13. Laravel压缩图片
  14. Ubuntu 20.04使用微信 (亲测有效)
  15. 高考数学95分能学计算机吗,数学模考5分到高考95分?
  16. 短时间如何过Java校招
  17. java自动发图文微博_使用node搭建自动发图文微博机器人的方法
  18. 傅里叶变换基函数可视化
  19. 九头牛的故事—你就是那个美丽的期待(刘俊平咨询师)
  20. springboot学习笔记(未完待续)

热门文章

  1. 计算机专业期末背书,据说大学学这些专业,期末考试最酸爽!
  2. [USACO Mar08] 游荡的奶牛
  3. deg怎么读_deg是什么意思_deg怎么读_deg翻译_用法_发音_词组_同反义词_degree(s) 度-新东方在线英语词典...
  4. 11、有线接入网技术
  5. Hive分桶之BUCKET详解
  6. CentOS7 本地搭建remix-ide
  7. 【ProjectEuler】ProjectEuler_046
  8. 前端工具-Yeoman模板 + 接收用户输入
  9. 学不动了,尝试用Android Jetpack Compose重写微信经典飞机大战游戏
  10. java一键换壁纸_Java 版下载必应每日壁纸并自动设置 Windows 系统桌面(改编自 C# 版)...