学习 React JS 相关总结

写在前面:
最近在写前端,感觉代码在页面不断堆积,以后维护和扩展也是一件头疼的事,对于做过几年后端开发的我来说,不合理的代码组织就像乱糟糟的房间一样看的难受,现在有必要学习这个框架了.

学习链接: 认识 React

写了一些 demo,随后集中整理一下

浅谈 Python 中 Synchronously, Multiprocessing, Threading 区别

1.Synchronously:

  • 线性执行
  • 同步方法
  • 耗时长

2.Multiprocessing if it’s CPU bound:

  • The multiprocessing library gives each process its own Python interpreter and each their own GIL(Global Interpreter Lock).

  • allows you to create programs that can run concurrently (bypassing the GIL)

  • use the entirety of your CPU core

      import multiprocessing
    
      def concurrent_multi_process():
          dids = []
          with concurrent.futures.ProcessPoolExecutor() as executor:
              results = executor.map(call_out_data, dids)
    
      def call_out_data(did):
          requests.adapters.DEFAULT_RETRIES = 5
    
          url = "http://202.205.91.21:60001/nrmv/canInfo"
          headers = {
              'Content-Type': 'application/json'
          }
    
          payload = json.dumps(
          {
              'appId': "",
              "did": did,
              "startTime": 'test',
              "endTime": '20220610000000',
              "limit": 1000000000,
              "nextPageStartRowKey": "",
              "reverse": 'false',
              "showColumns": ["`did`", "`3014`", "`2602`", "`2603`", "`2204`"],
              "token": ""
          })
          response = requests.request("POST", url, headers=headers, data=payload)
          print(response)
    
          if (response.status_code == 200 and 'data' in response.json()):
              data = response.json()['data']
              return data
    

3.Threading if your program is network bound:

  • it’s perfect for I/O operations such as web scraping because the processor is sitting idle waiting for data.

      import threading
    
      def thread_process():
          dids = []
          with concurrent.futures.ThreadPoolExecutor() as executor:
              results = executor.map(call_out_data, dids)
    

针对中农的大数据服务器,测试了请求3645 次 不同类型下的性能比较,可以看出,使用 thread 方式效果最优秀

Python 导入 Module 错误

ModuleNotFoundError: No module named ‘XXX’ in Python

The Python “ModuleNotFoundError: No module named ‘XXX’” occurs when we forget to install the XXX module before importing it or install it in an incorrect environment. To solve the error, install the module by running the pip install XXX command.

Open your terminal in your project’s root directory and install the XXX module.

notice:

👇️ in a virtual environment or using Python 2

pip install XXX

👇️ for python 3 (could also be pip3.10 depending on your version)

pip3 install XXX

👇️ if you get permissions error

sudo pip3 install XXX

👇️ if you don’t have pip in your PATH environment variable

python -m pip install XXX

👇️ for python 3 (could also be pip3.10 depending on your version)

python3 -m pip install XXX

👇️ for Anaconda

conda install -c anaconda XXX

The Python error “ModuleNotFoundError: No module named ‘XXX’” occurs for multiple reasons:

  • Not having the XXX package installed by running pip install XXX.
  • Installing the package in a different Python version than the one you’re using.
  • Installing the package globally and not in your virtual environment.
  • Your IDE running an incorrect version of Python.
  • Naming your module XXX.py which would shadow the official module.
  • Declaring a variable named XXX which would shadow the imported variable.

If the error persists, get your Python version and make sure you are installing the package using the correct Python version.

For example, my Python version is 3.10.4, so I would install the XXX package with pip3.10 install XXX.

pip3.10 install XXX

👇️ if you get permissions error use pip3 (NOT pip3.X)

sudo pip3 install XXX

If the “No module named ‘XXX’” error persists, try restarting your IDE and development server / script.

You can check if you have the XXX package installed by running the pip show XXX command.

👇️ check if you have XXX installed

pip3 show XXX

👇️ if you don’t have pip setup in PATH

python3 -m pip show XXX

The pip show XXX command will either state that the package is not installed or show a bunch of information about the package, including the location where the package is installed.

If the package is not installed, make sure your IDE is using the correct version of Python.

If you have multiple Python versions installed on your machine, you might have installed the XXX package using the incorrect version or your IDE might be setup to use a different version.

For example, In VSCode, you can press CTRL + Shift + P or (⌘ + Shift + P on Mac) to open the command palette.

Then type “Python select interpreter” in the field.

Your IDE should be using the same version of Python (including the virtual environment) that you are using to install packages from your terminal.

👇️ check if you have XXX installed

pip3 show XXX

👇️ if you don’t have pip setup in PATH

python3 -m pip show XXX

👇️ uninstall XXX

pip3 uninstall XXX

👇️ if you don’t have pip setup in PATH

python3 -m pip uninstall XXX

👇️ install XXX

pip3 install XXX

👇️ if you don’t have pip setup in PATH

python3 -m pip install XXX

https://bobbyhadz.com/blog/python-no-module-named-numpy

深度学习浅显理解

基于深度学习卷积神经网络分析道路破损情况

1.1 研究背景

    道路的建设不仅促进了地域之间的交流,也使得地域之间的经济交流更加密切,更好的促进了社会和经济的发展,但道路建设到了后期会面临着很多问题,比如路面保养,路面修缮,路面特殊情况的处理。如果这些问题不能及早的发现,不仅对车和行人安全造成巨大的隐患,还会缩短路面的使用期限,缩短路面的寿命。若能及时发现和排查问题所在,防患未然,能极大的缩小道路修缮的维护成本。

    当前,路面检测主要是靠两种途径来完成的,一种是人工实地勘测,另一种是使用影像检查路面情况。

    人工实地勘测工作量大,效率低,检查中会影响车辆以及行人,也会造成一些安全上的隐患,并且人工检检查会有主观倾向性,和实际测量结果之间可能有很大的误差。

    后来使用影像技术来监测路面破损程,即对路表面拍摄高清晰照片,通过图像处理获取路面裂缝,泛油与修补等信息。该方法能极大的提高路面检测的效率和精度,同时大大的降低劳动成本。

    随着技术的发展基于人脑神经元网络抽象的人工神经网络(Artificial Neural Networks,ANNs)自20世纪80年代以来,成为图像处理和人工智能领域研究的新兴热点。深度学习(DeepLearning,DL)的起源来自于 ANNs,宏观的可以认为 DL 属于 ANNs 中含有多隐层感知器的一种特殊网络结构。而深度学习技术在图像处理领域的迅速发展,深深的影响了在路面图像破损目标识别方面的研究进展,也为我们提供了一个很很好的解决问题的方式

1.2 传统路面裂缝检测算法国内外研究进展

1.2.1 路面裂缝图像预处理算法

    在图像识别技术中,由于路面裂缝图像的采集来源于人工干预方式,因此得到的路面裂缝数据集质量会受到诸如光照强度、雨雾天气、路面油渍等各种外界因素的影响,而路面裂缝图像质量的好坏直接影响着图像识别算法的设计及识别效果精度。要想提高图像识别算法各方面的性能,除了在原始算法基础上进行优化以外,图像预处理技术在整个图像处理技术中占有非常重要的地位。根据对目前已有预处理算法的研究,可以将比较广发使用的图像预处理方法分为两大类:图像背景差法和图像细节增强法。

    图像背景差法是指将当前所获得原始图像与经过处理的背景图像进行求灰度差运算,得到目标区域灰度图的一种方法。Cheng 等[1/6]提出了一种基于模糊逻辑的路面裂缝检测算法,该算法的主要思想基于路面图像中裂缝处的灰度值比周围的背景图像灰度值低,且裂缝处的像素比背景环境的像素更为连续的事实。该方法首先通过确定差分图像灰度的亮度隶属函数来确定裂缝处像素比周围背景的灰度值暗多少,其次求出路面图像中裂缝像素的灰度域值范围,最后检查较暗像素区域的连通性来消除伪裂缝的存在。研究表明,该方法可以有效的检测到包含大量噪音的路面图像中存在的薄弱裂缝。

    细节增强法是根据裂缝与背景图像在路面图像中体现出的频域不同,裂缝目标表现出高频特征,而噪音表现出的是低频特征,对路面图像中的高频特征进行增强,以此来加强路面图像中裂缝与背景部分的对比度,进而进行裂缝目标识别。Zou 等[2/7]将小波包引入到路面图像预处理环节的降噪过程中,该算法将路面图像分解后,在路面图像的每一级尺度上按照不同的参数进行降噪处理,最后对路面图像进行重建。在以实际路面图像为数据的基础上进行实验,结果表明该方法表现出其高效性,并且可以有效的处理路面图像的噪音。然而,随着输入的路面裂缝图像的多样性,应用系统很难自适应地调整非线性函数的参数。

    对比背景差法和细节增强法可见:在处理范围方面,前者偏向于路面裂缝图像的宏观处理方向,后者着重于路面裂缝图像的微观处理方向;数据处理量方面,前者数据计算量明显低于后者数据计算量;在适应性方面,前者不仅可以处理高频信息,还可以很好的处理低频噪音等信息,因此普适性高于后者。

    两种方法的缺点:背景差法容易漏掉对路面裂缝细节信息的处理,细节增强法则因其繁杂的数据计算量而致使其适应性不好。

1.2.2 路面裂缝图像分类算法

    裂缝在路面破损图像中,表现出诸如龟裂、多纹理性、多方向性等多样性。相关领域专家分别对不同特征的路面裂缝图像进行单独研究[3/8],现在已经存在的路面裂缝分类算法有很多种。对目前普遍使用的路面裂缝分类算法,大体可以划分为下面这八类:基于阈值的路面图像分割法、基于边缘检测的识别方法、基于多尺度[4/12]检测的裂缝识别方法、基于裂缝纹理的检测法、基于多特征融合的路面裂缝检测方法、基于图论的裂缝检测方法、基于深度学习的路面裂缝识别方法、以及其他分类方法。

    其中基于阈值的路面图像分割法中有一个是老师(TANAKA Naoki)等人早年间的研究,利用数学形态学的几种算子对路面裂缝进行检测,其适用于模糊的裂纹,但对于微小裂缝而言,该方法不太适应用[5//10]。还有就是 Xu[6/14] 提出将路面裂缝图像统一划分为8x8像素大小的网格图像,基于含有网格的路面图像检测其网格边界是否包含“波谷”来断定图像中裂缝的存在可能,该方法称为 GCA 的边缘检测算法。判别裂缝的方式如下,如果网格图像中存在“波谷”,那么将边界上像素中灰度最小值设置为种子点,然后校验和跟踪这些种子点即可。该方法是在多次不同情况下进行驾驶检测的,识别结果发现在反复多次的检测中具有良好的准确性。

    尽管目前路面裂缝识别算法已经相当成熟,但是仍然存在各种各样的条件限制着路面裂缝识别的准确率及实时效果[7/18]。

1.3 目前存在的主要问题

    现如今的图像采集设备及技术一直在稳步前进,但是采集到的路面图像依旧会受采集设备的拍摄角度、光照、遮挡等外界因素的影响,通常获取的路面图像都会出现灰度不均匀[8/26]。传统的裂缝识别算法,在对这些路面裂缝图像进行分类识别前,均需先进行路面图像的去模糊、去除噪声、增强对比度等预处理工作,以减少后期处理中较大数据处理量及较高误识别率。

    综上,在路面裂缝图像分类识别过程中,目前主要存在以下几类问题:

    采集不到无噪音影响的纯净路面裂缝图像数据[8/27],反而想要得到这样的数据,需要非常昂贵的成本;

    传统路面裂缝图像的预处理、特征提取、分类器训练以及最终的分类,均需要拥有多年图像处理工作的专业工程师进行人工辅助,这些过程均以经验为驱动,未能实现自动处理;

    传统的路面裂缝图像分类技术通用性较差,致使最终的分类精度到了瓶颈期,上升空间较小。

1.4 深度学习神经网络相关介绍

    深度神经网络的构思来源于生物神经系统,因此深度神经网络模型亦是以神经元为基础的。同时深度神经网络具有并行分布处理图像数据的特点、网络模型兼备高鲁棒性及高容错能力、并且分布式存储数据及高度学习能力、能够充分逼近复杂的非线性关系等优点,让深度神经网络在极短的时间内凸显出其超群的优越性。

1.4.1 单隐层神经网络

    基于神经元多输入单输出的特性,通过重构网络拓扑、节点特点及学习规则来对神经网络进行建模。一个常见的简单神经元数学模型,如下图 1.1 所示。

    单隐层神经网络模型相当于是对神经元数学模型进行一个宏观的包装,模型主要包括三层,即:输入层、隐层和输出层。单隐层神经网络与神经元模型不同的是,神经元模型是单输出,而单隐层神经网络模型是多输出,其网络结构如图 1.2 所示。

1.4.2 多隐层神经网络

    对单隐层神经网络进行延伸可知,当隐层个数超过2 层(包括2 层)时,我们就将这类网络定义为多隐层神经网络。多隐层神经网络是一种包含多个隐层、全连接层的有向无环的网络结构。值得注意的是这类网络只有输入层、隐层和输出层。如下图 1.3 所示为简单的多隐层神经网络结构图:

1.4.3 深度学习网络

    深度学习是目前机器学习领域比较热门的一项技术。从网络的结构来说,我们可以认为深度学习网络是多隐层神经网络的一种特殊形式,该技术可以打破传统神经网络的瓶颈,建立更类似于生物神经网络分析处理诸如声音、文本、图像等数据的数学模型。深度学习的网络范式包括数据、模型、优化和求解四步,基于人工神经网络,深度学习网络加入了更多的层,如卷积层、池化层、Dropout 层等。

    相对于多层神经网络模型的以下几个常见的不足:1、人工提取原始数据特征的方式,在面对大数据时,过滤数据量,需要耗费大量的时间,并且对特征尺度的提取比较难把握,训练出来的模型对噪音敏感度较高;2、更高的精确度意味着更深的网络层次,而随着网络层的不断加深,网络难免出现梯度扩散问题;3、多层神经网络里面没有设置处理时间序列的参数,网络不能处理跟时间相关的数据;深度学习网络的下面几个特点,刚好弥补了多层神经网路的不足:1、深度学习网络自动提取输入数据的特征,无需人工参与,且网络自动获取的数据特征更能体现实物的特征,可以获得泛化能力更强的网络模型;2、根据不同的应用,可以将深度学习网络模型调整为适用于该应用的网络架构;3、深度学习网络加入了反馈和时间参数,使网络的应用范围更广。

1.5 卷积神经网络介绍

    卷积神经网络是由多层感知器经过变化而得。由生物学家Hubel 和Wiesel 在早期关于猫视觉皮层的研究发展而来。视觉皮层的细胞是一个构造十分复杂的结构。这些细胞对视觉输入空间的子区域非常敏感,称之为感受野,以这种方式平铺覆盖到整个视野区域。这些细胞的基本类型有两种,简单细胞作为一种其作用是响应来自感受野范围内的边缘刺激模式。不同于简单细胞,复杂细胞的接收域范围更大,而且它具有局部不变性。卷积神经网络是非全连接的多层神经网络,每层的组成是多个二维平面,多个独立的神经元组成了对应的二维平面,正如卷积神经网络模型如图 1.4 所示,它包含了卷积层和亚采样层两个网络结构。

检测不同特征的不同滤波器在输入文件上被卷积,并且输出一组激活图,其被传递到CNN中的下一层[9/斯坦福大学]。

公式用于确定激活图的维度:

$(N + 2P-F)/ S + 1$; 其中$N =图像(输入)$文件的尺寸

  $P =填充$

  $F =滤波器的尺寸$

  $S = Stride$

1.5.1 激活功能

激活功能是放置在神经网络末端或之间的节点。它们有助于确定神经元是否会发射。

有不同类型的激活函数,如图 1.8 所示,这里重点讲一下整流线性单元(ReLU)。

ReLU函数是当今神经网络中使用最广泛的激活函数。ReLU 相对于其他激活功能的最大优势之一是它不会同时激活所有神经元。从上面的 ReLU 函数图像中,我们会注意到它将所有负输入转换为零,并且神经元不会被激活。这使得它非常有计算效率,因为每次激活的神经元很少。它不会在正区域饱和。在实践中,ReLU 的收敛速度比 tanh 和 S 形激活函数快6倍。

ReLU提出的一些缺点是它在负区域饱和,这意味着该区域的梯度为零。在梯度等于零的情况下,在反向传播期间,所有权重都不会更新,为了解决这个问题,我们使用Leaky ReLU。此外,ReLU功能不是以零为中心的。这意味着为了使其达到最佳点,它必须使用可能更长的锯齿形路径。

1.5.2 池层

可以在 CNN 架构中的卷积层之间看到池化层。该层基本上减少了网络中的参数和计算量,通过逐渐减小网络的空间大小来控制过度拟合。

该层有两个操作; 平均合并和最大合并。这里只讨论 Max-pooling。

1.5.3 最大池

就像名字所说; 只会从游泳池中取出最大值。这实际上是通过使用滑过输入的滤波器完成的; 并且在每一步都取出最大参数,其余参数被删除。这实际上是对网络进行下采样。与卷积层不同,池化层不会改变网络的深度,深度维度保持不变。

Max-pooling后输出的公式:

$(N - F)/ S + 1 $; 其中 $N =汇集层的输入维度$

$F =滤波器的尺寸$

$S = Stride$

1.5.4 完全连接的层

在该层中,神经元与先前层的所有激活完全连接。因此,可以通过矩阵乘法后跟偏置偏移来计算它们的激活。这是CNN网络的最后阶段。卷积神经网络实际上由隐藏层和完全连接的层组成。

卷积神经网络训练过程

卷积神经网络可以学习大量的输入到输出之间的映射关系,即其本质就是一种从输入端到输出端的映射,在学习的过程中不需要输入与输出之间存在任何的可以用表达式表示出的关系,只要用已知的数据对网络加以训练,网络最终就能够具有输入到输出之间的映射能力。卷积神经网络的训练原理是根据链式求导计算损失函数对每个权重的偏导数,然后根据梯度下降公式对权重进行更新。采用的是反向传播算法。主要包括四个步骤:

前向传播阶段:

(1)从样本集中取出一个样本(M, N ),将 M 输入网络;

(2)计算对应的实际输出值O;

1.6 路面裂缝图像预处理及识别方法

1.6.1 路面裂缝类别

    公路路面在长时间的自然条件作用,以及车辆的行驶速度、紧急刹车、车辆载重等影响下,公路路面会出现不同种类、不同程度的破损,在影响道路服务的能力同时还会影响到车辆的安全,所以需要进行道路维护。由于裂缝类型相异,所以针对不同类别的路面破损情况应采取不同的维护方法,这样不仅有利于维护的效率,而且还能节约维护成本,节约资源。所以能够准确的对路面破损的类别、破损的程度进行分类识别和评定,对路面维护和提高服务能力具有重要意义。以下是一些常见的裂痕种类:

    横向裂缝,横向裂缝是指与路面中心线垂直的裂缝,裂缝有的贯穿部分路面,有的贯穿整个路面,长短不一且呈现弯曲状,有深有浅并伴有少量的细小分支,如图 3.1 所示。横向裂缝的成因主要是由温度变化导致的路基和路表不均匀缩涨和路基差异性沉陷,同时在积水的作用下对路面裂缝造成冲刷致使裂缝深度加深,导致分离加重,再由路面设计不合理、施工质量低劣或车辆超载等因素的影响导致混凝土伸缩和沥青分离出现裂缝变形。

    纵向裂缝,纵向裂缝是指与行车方向基本平行的裂缝,其裂缝的走向较为单一且长度和宽度不一,并且形状带有弯曲,只有少量的纵向裂缝带有小分支。纵向裂缝一般由于在施工过程中路基压实度不够、不均匀、土块粉碎不充分所引起的,多出现在路肩和行车道部位,随着积水的冲刷以及车辆超载极易引起裂缝宽度的增加,危害行车安全,增加维护成本。

    网状裂缝,网状裂缝也叫龟裂,在载荷重复作用的情况下导致基层被软化,形成大量横向和纵向裂缝相互交错在一起的密集小块,呈现网格状,如图 3.3 所示。网状裂缝的缝宽在 1mm 以上,两条裂缝的距离在40cm 以下,其区域边缘构成的总面积在 1m2 以上的网格状裂缝。造成网状裂缝的产生主要原因有路基不实、微小裂痕经过长时间碾压、重复载荷等。网状裂缝如果不及时处理,在温度变化较大、雨水冲刷、车辆超重等情况下极易形成大面积的破坏。

    块状裂缝,块状裂缝是由不规则少量的网状裂痕形成的,如图 4.4 所示。块状裂缝其横纵裂缝较为稀疏,裂缝块的大小一般在9m2 之内。大多都是由于路面老化、久经风雨造成的。

1.6.2 路面裂缝破损程度评定

    不同环境的路面均会出现不同类型、不同破损程度及范围的裂缝,为了更加准确具体的掌握路面破损的情况,可以及时对破损路面进行修复,所以对路面破损程度的严重性以及综合因素考虑变得十分重要。所以为了便于比较和分类,通常使用 Pavement Condition Index(PCI)作为路面破损状况的评价标准[34]。路面状况指数 PCI 的取值范围为 1 到 100,越接近 100 表示路面状况良好,根据 PCI 数值的大小,可将路面状况分为 5 个等级,对于较优的路面状况,就可以排除在需要修复范围之外,而对破损程度不一的状况则需要进行不同程度的修复。

    路面状况指数 PCI 的计算公式为:

$$PCI = 100 - DR^{0.412}$$

    其中 DR 为综合破损率,是沥青路面破损调查指标,其计算公式为:

$$DR = D/A = D_{ij}K_{ij}/A$$

    其中 D 表示评价路段内的折合破损面积;A 表示评价路段的路面总面积;$D_{ij}$ 表示第 i 类破损、第 j 种破损程度的实际破损面积;$K_{ij}$ 为第 i 类破损、第 j 种破损程度的换算系数;i,j 分别表示破损类型和破损程度。

#### 路面破损换算系数(K)
破损类型 外观描述 破损程度 换算系数
横向裂缝 轻:少分支、缝隙小、缝壁无散落;
中:少分支、缝隙较小、缝壁散落轻微;
重:少分支、缝隙较大
轻/中/重 0.6/0.8/1.0
纵向裂缝 轻:少分支、缝隙小、缝壁无散落;
重:少分支多、缝隙较大、缝壁散落严重
轻/重 0.2/ 0.4
网状裂缝 轻:缝细、缝壁无散落、变形不明显;
重:网格众多、缝壁散落严重、缝隙较大
轻/重 0.4/0.6
块状裂缝 轻:缝细、缝壁无散落、块状大;
重:缝宽、缝壁散落严重、块状小
轻/重 0.2/0.4

1.7 路面破损图像预处理

    由于公路路面状况较为复杂,且受到环境、路面清洁情况、图像采集角度、光照强度以及光照均匀程度的影响,使得图像采集准确度十分困难,并对以后的特征提取带来诸多困难。为了提高图像质量,需要消除采集过程中的不利影响,使得特征更加精确明显,更好的表达裂缝的破损程度及类型等信息,所以需要对目标图像进行预处理,不仅有利于训练处理,还可以提高训练效果和识别精度。在路面图像预处理过程中,常用的方法有:灰度变换、直方图均衡化、中值滤波、形态学处理等,接下来对四种方法分别进行简要介绍。

1.7.1 灰度变换

    图像灰度变换是为了改善画质,使目标图像显示的效果更加清晰,可以有选择性的突出目标图像中的特征区域,并抑制图像中的干扰因素(噪声)。其主要原理是通过再次计算数据图像中灰度值的范围,使得原始图像的像素值得到重新分配,从而增强图像的对比度。灰度变换常用的方法有:图像求反、对数变换、灰度切割、位图切割、灰度的线性变换。本文使用灰度得线性变换方法对路面裂缝图像进行处理。记原始图像的灰度为 $f(x, y)$,经过变换后的数据图像灰度记为 $g(x, y)$,灰度变换的计算式如下:

$$g(x,y)=\frac{Y_{b}-Y_{a}}{X_{b}-X_{a}}\left[f(x,y) - X_{a}\right] + Y_{a}$$

其中,$X_{a}$ 表示原始图像灰度的最小值,$X_{b}$ 表示最大值;$Y_{a}$ 表示经过变换后的图像灰度值的最小值,$Y_{b}$ 表示最大值,即 $\frac{Y_{b}-Y_{a}}{X_{b}-X_{a}}$ 表示线性斜率。斜率大于 1 时,输出的图像对比度增加,小于 1 时对比度减小,等于 1 时图像灰度值上移或下移,小于 0 就会使暗区域变亮,亮区域变暗。通过灰度变换图像的灰度值范围由$(X_{a}, X_{b})$ 变为 $(Y_{a}, Y_{b})$。

1.7.2 灰度变换

####    直方图均衡化利用图像直方图对对比度进行调整,在路面裂缝图像中,路面背景与裂缝的对比度相对较为接近。直方图均衡化对图像进行非线性拉伸,重新分配图像像素值,而把给定的直方图分布变成均匀分布的直方图。在相对信息量较大的图像中,通过将图像的对比度增强达到数据图像清晰度增加的目的。该方法较为直观,而且操作具有可逆性,可以恢复原始的直方图。

1.7.3 中值滤波

####    中值滤波对噪声有良好的滤除作用,能够有效的保护信号的边缘。在路面裂缝图像采集过程中,由于各种各样噪声的影响不仅不利于影响了训练速度的提升也严重干扰了图像的特征提取。中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理方法,能够很好地抑制图像中的噪声。

    中值滤波通过把数字图像中的一个点值通过用该点领域中各个点值的中值来代替,使得它周围的像素值更加接近真实值,从而使孤立的噪声点被消除掉。因为噪声的存在,使得该点的像素会比周围的像素亮或者暗许多,所以通过对像素由小到大重新排列之后,亮的点或者暗的点就会被排到两侧,并取中间位置的像素灰度值来替代待处理像素的值,从而到达消除噪声的目的。

1.7.4 形态学图像处理

####    形态学图像处理方法可以有效的解决形状识别、抑制噪声、纹理分析、边缘检测、图像压缩等问题,主要以几何结构为基础,且提取的边缘较为光滑,断点少,可以有效的保持原始图像,而能否有效的提取信息的关键在于结构元的选择,结构元的选择必须比原图像要简单并且有边界。路面裂缝图像经过灰度变换、直方图均衡化和中值滤波处理后仍然会存在孤立的噪声点或者细小的裂缝,为了减弱噪声点和细小裂缝对路面图像特征提取的影响需要使用形态学处理方法消除这些噪声点和连接细小裂缝。

参考文献 :

[1] MOHAN A, POOBAL S. Crack detection using image processing: a critical review and analysis[J]. Alexandria Engineering Journal

[2] JIANG Ming-hu, GIELEN G, DENG Bei-xing, et al. A fast learning algorithm for time-delay neural networks[J].Information Science,2002,148(1-4):27-39

Salesforce 架构篇总结(三)Service 层的一些原则

主要目标

创建一个 Service 层的 class 并且在应用中高效的使用
暴露出一个用 Service 层做的 API

创建 Service

下面介绍的这个方法展示了使用 service 利用 discount 来建立一组 discount

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public with sharing class OpportunitiesService
{
public static void applyDiscounts(Set<Id> opportunityIds, Decimal discountPercentage)
{
// Validate parameters
if(opportunityIds == null || opportunityIds.size() == 0)
{
throw new OpportunityServiceException('Opportunities not specified.');
}

if(discountPercentage < 0 || discountPercentage > 100)
{
throw new OpportunityServiceException('Invalid discount to apply.');
}

// Query Opportunities and Lines (SOQL inlined for this example, see Selector pattern in later module)
List<Opportunity> opportunities =[select Amount, (select UnitPrice from OpportunityLineItems)
from Opportunity where Id in :opportunityIds];

// Update Opportunities and Lines (if present)
List<Opportunity> oppsToUpdate = new List<Opportunity>();
List<OpportunityLineItem> oppLinesToUpdate = new List<OpportunityLineItem>();

Decimal factor = 1 - (discountPercentage == null ? 0 : discountPercentage / 100);

for(Opportunity opportunity : opportunities)
{
// Apply to Opportunity Amount
if(opportunity.OpportunityLineItems != null && opportunity.OpportunityLineItems.size() > 0)
{
for(OpportunityLineItem oppLineItem : opportunity.OpportunityLineItems)
{
oppLineItem.UnitPrice = oppLineItem.UnitPrice * factor;
oppLinesToUpdate.add(oppLineItem);
}
}
else
{
opportunity.Amount = opportunity.Amount * factor;
oppsToUpdate.add(opportunity);
}
}

// Update the database
SavePoint sp = Database.setSavePoint();

try
{
update oppLinesToUpdate;
update oppsToUpdate;
}
catch (Exception e)
{
// Rollback
Database.rollback(sp);
// Throw exception on to caller
throw e;
}
}

public class OpportunityServiceException extends Exception {}
}

Salesforce 架构篇总结(二)理解 Service 层业务遵循的规则

主要目标

理解 Martin Fowler 为了做企业级架构而分离出 Service 层的缘由
理解为什么 Apex 代码要属于 Service 层
在应用和平台的开发中如何很好的契合 Service 层的代码
在 salesforce 平台上用代码去实现 Service 的架构

简单概述

上一篇 Blog 只是简单的介绍了 SOC 思想,将软件的结构抽象到层级应用的逻辑方面,本篇 Blog 主要将目标集中在如何去定义和实现 Service 层,它也是别的层级或者 API 调用的关键步骤。

层级架构之间的关系图:

ServiceLayerSketch up-w250

Service 层对实现的业务层、运算层和一些执行业务的逻辑 Process 有一个清晰和严格的封装,同时 service 层必须保证足够的功能专一和抽象,它能够适应后期功能的多次迭代和灵活的可扩展性。下面的内容是如何使用 Apex 代码来实现 Service 层的业务逻辑,同时说明如何在 Force.com 资源有限的情况的下合理的利用资源去实现它。

使用 Service 层的对象

客户端(client)执行 Service 层的业务逻辑,比如像 UI controller 或者 Batch Apex 等。

值得考虑使用 Service 层的一些方向:

Service 层的

1
2
3
4
5
6
注意:

上图中没有提到 Apex Trigger,因为 Trigger 的逻辑属于 Domain layer,它和 Object 联系非常
紧密,在 Domain 层的业务逻辑通过 platform UI 或者 APIs 或多或少的会和 Service 层联系到一


对 Salesforce 平台的创新和适应性的思考

想象一下有这么一个场景,当写了一段 feature 代码,需求只要一变就得重新对代码进行重构,或者更糟糕的是由于害怕之前写的逻辑被破坏,索性不敢动之前的逻辑,然后出现了大量的重复的代码,真是很糟糕的体验。

设计上的一些考究

  • 命名规范:Service 层应该足够抽象而且其意义,同时应该很广泛来涵盖客户端的很多情况,这些方面可以表现在对类、方法、参数名的命名规范上,什么时候用动词(verbs),什么时候用名词(nouns)都要有所思考;确保名字所表达的是种一般情况而非特殊情况,举个例子,这个方法名是以业务操作来命名的 InvoiceService.calculateTax(…) ,而第二个方法名是以特定的业务操作来命名的 InvoiceService.handleTaxCodeForACME(…) 应该避像第二种这样的的命名方式

  • 平台 / 协调一致:设计一个签名的算法和 Salesforce 平台进行交互是一个很好的实践,尤其要使用 Bulkificaiton 的时候,一个主要需要考虑的因素是,在所有运行在 Force.com 上的代码都是 Bulkificaiton,要考虑调用服务器端的代码参数数组化,而不是一个单一的参数集,举个例子,这个方法就可以使用 Bulkificaiton => InvoiceService.calculateTax(List taxCalulations),而这个方法 => InvoiceService.calculateTax(Invoice invoice, TaxInfo taxCodeInfo),由于参数是单一参数集,也应该尽量去避免

  • SOC 方面的考究:在应用当中 Service 层的代码利用很多 Objects 封装一些任务或者 Process 业务逻辑,与之相对应的是,有些代码关联着特定的 validationfield values 或者 calculations,通过插入、更新、删除触发Trigger 来影响其相对应 Object, 这些代码一般存放在 Trigger 当中,并且可以保留在那里

  • 安全性:Service 层的代码和那些被调用的代码应该确保用户安全,要确保这一点使用 with sharing(with Security Settings enforced)修饰符,尤其需要注意的是如果使用 global 修饰符暴露了太多关键代码,就需要引起注意。如果一个 Apex 类的逻辑必须通过一些 Recodes 让外部的用户可见,那么代码必须提炼它的执行环境,越简略越好,一个好的办法是使用私有的 Apex 内部类,使用 without sharing
    关键字

  • 编组:简言之,避免指定如何处理与 Service 层交互的方面错误信息,因为某些方面最好留给服务的调用者,只管原样抛出异常就好(it is typically best to leverage the default error-handling semantics of Apex by throwing exceptions. )

  • 整合服务:虽然客户端可以一个接一个的执行多次 callout,但这么做会很低效,也会造成一些数据库事务方面的问题,最好的办法是建一个整合服务( compound services)(compound services),让一次 callout 涵盖多个客户端的请求。同样很重要的是尽可能优化 Service 层的 SOQL 和 DML 操作。当然了这并不意味着不能 callout 更细节的逻辑单元;如果需要的话,可以开发特定的单元去以供客户端 callout

  • 事务管理和无状态: Service 层的客户端经常有一些拥有长存活时间且不同的 Process 请求和一些消息用来执行和处理,举个例子,一个单一的请求和多个请求分隔成单独的作用范围到服务器端:管理状态(比如 Batch Apex)或者复杂的 UI 都是通过它们自己的页面状态来接受很多请求的,在状态管理上最好的方式是在做一次 callout 到 Service 层时,封装数据库操作和服务状态。换句话说,使 Service 端保持无状态,以使调用的环境灵活地使用它们自己的状态管理解决方案。例如,一个在数据库事务的作用域同样应该被包括在每一个 Service 层的方法当中,以便于调用者不用去考虑和其相关的 SavePoints

  • 配置:在 Service 层中,可能有常见的配置或行为被覆盖,合理使用方法重载,接受一个共享的选项参数,类似于 Apex 中的 DML 方法

Service 层在 Apex 中的应用

情景介绍:假设在 Opportunity 页面有个自定义 Button 当点击 Button 会出现一个 Visualforce 页面,提示用户对 Opportunity Amount(或相关联的 Opportunity Line)项目应用一个折扣百分比。
实例展示如何将 OpportunitiesService.applyDiscounts 方法应用到比如 Visualforce、Batch Apex、 或者 JavaScript Remoting 这些地方上。

下面的 Code 处理的是通过 StandardController 选择的单个 Opportunity,注意:controller 的错误信息是 controller 自己来处理的,而非 service,因为 visualforce 有其自身的错误表现形式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public PageReference applyDiscount()
{
try
{
// Apply discount entered to the current
Opportunity OpportunitiesService.applyDiscounts(new Set<ID>{ standardController.getId() }, DiscountPercentage);
}
catch (Exception e)
{
ApexPages.addMessages(e);
}

return ApexPages.hasMessages() ? null : standardController.view();
}

下面的 Code 展示了通过 StandardSetController 处理多个 Opportunities

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public PageReference applyDiscounts()
{
try
{
// Apply discount entered to the selected Opportunities
OpportunitiesService.applyDiscounts(
// Tip: Creating a Map from an SObject list gives easy access to the Ids (keys)
new Map<Id,SObject>(standardSetController.getSelected()).keyValues(),
DiscountPercentage
);
}
catch (Exception e)
{
ApexPages.addMessages(e);
}

return ApexPages.hasMessages() ? null : standardController.view();
}

下面的 Code 展示了如何使用 Batch Apex 处理大量的数据,注意和之前代码的区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public with sharing class OpportunityApplyDiscountJob implements Database.Batchable<SObject>
{
public Decimal DiscountPercentage { get; private set; }

public OpportunityApplyDiscountJob(Decimal discountPercentage)
{
// Discount to apply in this job
this.DiscountPercentage = discountPercentage;
}

public Database.QueryLocator start(Database.BatchableContext ctx)
{
// Opportunities to discount
return Database.getQueryLocator('select Id from Opportunity where StageName = \'Negotiation/Review\'');
}

public void execute(Database.BatchableContext BC, List<sObject> scope)
{
try
{
// Call the service
OpportunitiesService.applyDiscounts(
new Map<Id,SObject>(scope).keySet(),DiscountPercentage);
}
catch (Exception e)
{
// Email error, log error, chatter error etc..
}
}

public void finish(Database.BatchableContext ctx) { }
}

下面的 Code 将 service 层打包起来,并且通过 JavaScript Remoting 暴露给客户端,供其调用

1
2
3
4
5
6
7
8
9
10
public class OpportunityController
{
@RemoteAction
public static void applyDiscount(Id opportunityId, Decimal discountPercent)
{
// Call service
OpportunitiesService.applyDiscounts(new Set<ID> { opportunityId }, discountPercent);
}
}

总结

在 Service 层提不断投入对更大的重用性和适应性的都带来很大的好处,同时也为应用程序实现 API 提供了一种更干净、更经济的方式之一。
原文:
Investing in a service layer for your application offers the engineering benefits of greater reuse and adaptability, as well as provides a cleaner and more cost effective way of implementing an API for your application, a must in today’s cloud-integrated world. By closely observing the encapsulation and design considerations described above, you start to form a durable core for your application that will endure and remain a solid investment throughout the ever-changing and innovative times ahead!

相关资料

Separation of concerns
Martin Fowler’s Service Layer Pattern
Martin Fowler’s Enterprise Architecture Patterns
Learn Service Layer Principles

知识扩展

With Sharing、Without Sharing 和 non-sharing-specified 修饰符的区别

在这里学到 Salesforce 相关的知识的

The fun way to learn Salesforce

Salesforce 架构篇总结(一)理解 SOC

主要目标

解释 SOC 用于商业的价值
在使用一些需求或者平台技术中使用 SOC 来适用一些解决方案
将 SOC 应用到 Force.com 中
什么时候决定使用 SOC 技术

1
2
3
4
5
作为一个 salesforce developer 不能仅仅停留在为客户解决一些业务逻辑方
面的问题,并且作为一个公司产品的后端程序猿,更为重要的是当产品迭代到一定
程度,随着难度的加大以及业务复杂度的加深,我们需要在开发中融入一些重要的
编程核心的思想,方便及时发现产品中的 bug 以及对产品后期可扩展性方面都有
不错的提升。

对于SOC(Separation of Concerns) 的理解

广义上来说SOC是一种分层思想的体现,在大多数OOP语言中都有涉及,这里不再赘述,但需要强调的是,代码的功能模块是可以不断复用的,我们不提倡 copy & paste,但要时刻想着复用,并且类的命名规范(class naming conventions),变量名的命名规范(variable naming conventions)都有助于代码可读性的提升,好的代码如同讲一段优美的故事,That is Good code should tell a story.

SOC 的一些好处

顺应技术革命的潮流(Evolution)
技术不断在进步的进步的同时保证代码层级之间是可以扩展,修改,甚至要做到可以使层级之间拆卸自如,回想前端框架数十年发展的太快了,心疼前端小伙伴,各种全家桶层出不穷,学也学不完,都是好学霸
对影响的管控(Impact management)
当修改或者拆卸掉一些层级组件的时候,应尽量避免影响到其他层级的功能,除非是出于设计的考究而去有意去修改的
角色及其职能(Roles and responsibility)
每一个层级都用其职能,不要低于或者高于其职能,比如丢弃掉一个客户端的应用或者类库,不是意味着丢去掉其业务层的逻辑,因为业务层是另一个层级的职责。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
salesforce  层级分类如下:

* 业务逻辑层(Business Logic Layer)
非编码(Declarative): Formula, Validation, Workflow, Process Builder, Sharing Rules
遍码(Coding): Apex Services, Apex Custom Actions

* 数据处理层 (Data Access layer)
非编码(Declarative): Data Loaders
编码(Coding): SOQL, SOSL, Salesforce APIs

* 数据库层 (Database Layer)
非编码(Declarative): Custom Objects, Fields, Relationships, Rollups
编码(Coding): Apex Triggers

在 Force.com 中使用 SOC

  • 在 App 中替代或者添加另一种 UI(Replacing or adding another UI to your app),需要考虑的是有多少代码需要去重写,或者有些 UI 的端口虽然什么都没做,但是影响到了 App 的 插入(inserting),更新(updating),验证(validating)或者计算处理(calculating)的一些功能。

  • 提供公用 API(Providing a public-facing API)评估一下所实现的 API 使用已有代码库的哪一部分,不要将一些动作行为的方法作为 API 基础的调用

  • 通过 Batch 类来提升应用层逻辑(Scaling your application logic via Batch Apex)使用 Batch 来增大数据吞吐量,使多个用户在登录相同的 UI 页面的时候有相一致的结果

  • 在 Visualforce 页面或者 Lightning Component controllers 中执行复杂的业务逻辑(Working with complex action methods in your Visualforce or Lightning Component controllers)言简意赅,使用 MVC 架构,很老生常谈的东西,在随后的章节会陆续介绍

  • 让一个新的开发人员能快速上手项目的架构(Making it easy for new developers to find their way around your code base)一个新的开发人员花在熟悉代码组织架构的时间也是衡量一个项目好坏的标准之一

第一篇 - Welcome to [Hexo]

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

@2018 Made by kakushuu