鸽子为什么喜欢盘旋_如何为鸽子回避系统设置数据收集

鸽子为什么喜欢盘旋

鸽子回避系统 (Pigeon Avoidance System)

Disclaimer: You are reading Part 2 that describes the technical setup. Part 1 gave an overview of the Pigeon Avoidance System and Part 3 provides details about the Pigeon Recognition Model.

免责声明:您正在阅读描述技术设置的第2部分。 第1部分 概述了鸽子避免系统, 第3部分 提供了有关鸽子识别模型的详细信息。

Now that we are already familiar with the problem, let’s set up Raspberry Pi to collect images. In this part, I will be talking about the technical setup of the Pigeon Avoidance System. This article consists of three subparts:

现在我们已经熟悉了这个问题,让我们设置Raspberry Pi来收集图像。 在这一部分中,我将讨论避免鸽子系统的技术设置。 本文包括三个子部分:

  1. Hardware setup

    硬件设定
  2. Orchestration software

    编排软件
  3. Production installation

    生产安装

The general approach of how to set up a Raspberry Pi for the data collection could be adapted for your own Deep Learning project. All the code from this part is located on GitHub and can be reused.

如何为数据收集设置Raspberry Pi的一般方法可以适合您自己的深度学习项目。 这部分的所有代码都位于GitHub上 ,可以重复使用。

Before I start, I would like to give credit to my friend and colleague Daniel, who helped me to set up the Raspberry and was my tech support when something suddenly didn't work in production.

在开始之前,我要感谢我的朋友和同事丹尼尔(Daniel) ,他帮助我建立了Raspberry,在生产突然失效的情况下,我还是我的技术支持。

硬件设定 (Hardware setup)

Recall the diagram from Part 1:

回顾第1部分中的图:

Image for post
Image 1: Pigeon Avoidance System Architecture Diagram
图1:鸽子回避系统架构图

Hardware-wise the Pigeon Avoidance System includes a Raspberry Pi and three external components: motion sensor, camera, and stepping motor. All is orchestrated through the Main Pipeline. Main Pipeline is the most crucial piece of software that we need to write. Even before we have the Pigeon Recognition Model trained, we need to have it in place to collect the data. However, we first need to connect the external components to the Raspberry Pi. For that, we will need to use GPIO (general purpose input/output) pins, which can be accessed through a Python program. The pins are enumerated as it is shown on the picture:

在硬件方面,Pigeon躲避系统包括Raspberry Pi和三个外部组件:运动传感器,摄像头和步进电机。 所有内容均通过主管道进行编排。 Main Pipeline是我们需要编写的最关键的软件。 甚至在我们训练鸽子识别模型之前,我们都需要准备好它来收集数据。 但是,我们首先需要将外部组件连接到Raspberry Pi。 为此,我们将需要使用GPIO(通用输入/输出)引脚,可以通过Python程序进行访问。 引脚被枚举,如图所示:

Image for post
official raspberry documentation树莓官方文档

Any of the GPIO pins can be designated as an input or output pin and used for a wide range of purposes. There are also two 5V pins, two 3.3V pins, and several 0V ground pins that we will use to connect external Raspberry components.

任何GPIO引脚都可以指定为输入或输出引脚,并可以用于多种用途。 还有两个5V引脚,两个3.3V引脚和几个0V接地引脚,我们将使用它们来连接外部Raspberry组件。

连接运动传感器 (Connecting motion sensor)

The first component that should be connected is a motion sensor. I used an infrared motion sensor HC SR-501 that can detect the infrared reflected by humans or animals. The diagram of the sensor is shown below.

应该连接的第一个组件是运动传感器。 我使用了红外运动传感器HC SR-501 ,它可以检测人或动物反射的红外光。 传感器的示意图如下所示。

Image for post
Image 3: Diagram of the Infrared Motion Sensor HC SR-501. Source: Freenove documentation
图3:红外运动传感器HC SR-501的示意图。 来源:Freenove文档

When a pigeon enters the active area of the sensor, it outputs a 3.3V signal to the GPIO pin it is connected to. The sensitive range of the motion detector is between two to seven meters and it can be calibrated by rotating the potentiometer R2. Potentiometer R1 calibrates the time delay between the high level outputs. There is also a jumper cap (yellow rectangle) that acts as a switch between two trigger modes:

当鸽子进入传感器的活动区域时,它会向连接的GPIO引脚输出3.3V信号。 运动探测器的敏感范围在2到7米之间,可以通过旋转电位计R2对其进行校准。 电位器R1校准高电平输出之间的时间延迟。 还有一个跳线帽(黄色矩形),用作两个触发模式之间的切换:

L: non-repeatable trigger mode. The sensor will output a high level after sensing the pigeon first time. It will continue to output the high level for the delay which is configured by R1. During this time, the sensor can not sense the pigeon. When the delay time is over, the sensor will output a low level.

L:不可重复的触发模式。 第一次检测鸽子后,传感器将输出高电平。 对于由R1配置的延迟,它将继续输出高电平。 在这段时间内,传感器无法感应到鸽子。 延迟时间结束后,传感器将输出低电平。

H: repeatable trigger mode. The sensor can detect the pigeon until it leaves the balcony. During that period, it is outputting at a high level. After the pigeon leaves, the sensor times a delay, also configured by R1, and then outputs a low level.

H:可重复触发模式。 传感器可以检测到鸽子离开阳台。 在此期间,它以高电平输出。 鸽子离开后,传感器会对同样由R1配置的延迟进行计时,然后输出低电平。

I am setting up the sensor into repeatable trigger mode, as I want to annoy the pigeons until they finally leave the balcony. Image 4 (red circle) shows how to connect the motion sensor to the Raspberry. While testing the setup I am using a Raspberry Pi extension board. In a production system, I put the jumpers directly to the Raspberry pins.

我将传感器设置为可重复的触发模式,因为我想让鸽子烦恼,直到它们最终离开阳台。 图4(红色圆圈)显示了如何将运动传感器连接到Raspberry。 在测试设置时,我正在使用Raspberry Pi扩展板。 在生产系统中,我将跳线直接放置到Raspberry引脚上。

Image for post
Image 4: Connecting External Components to Raspberry Pi
图4:将外部组件连接到Raspberry Pi

连接步进电机 (Connecting the stepping motor)

The stepping motor will rotate a shooing device that scares pigeons away. I use a stepping motor in my setup as it can be rotated by a specific angle and for a defined time interval.

步进马达将旋转使鸽子吓跑的击球装置。 我在设置中使用了步进电机,因为它可以旋转特定的角度并保持一定的时间间隔。

The stepping motor has a 5-way socket that connects to the stepping motor driver. The stepping motor driver is used to convert the weak input signal that comes from the Raspberry into a robust control signal to drive the stepping motor.

步进电动机具有一个5通插座,该插座连接到步进电动机驱动器。 步进电机驱动器用于将来自Raspberry的微弱输入信号转换为强大的控制信号,以驱动步进电机。

Image for post
Image 5: Stepping Motor Driver Schematic Diagram. Source: Freenove documentation
图5:步进电机驱动器原理图。 来源:Freenove文档

The input signals to the stepping motor driver IN1-IN4 correspond to the output signals A-D that control the position of the stepping motor. The position control can be done programmatically. The stepping motor requires an external 5V power source that should share a common ground with the Raspberry Pi. Image 4 shows how to connect the stepping motor with the Raspberry Pi (green circles).

到步进电动机驱动器IN1-IN4的输入信号对应于控制步进电动机的位置的输出信号AD。 位置控制可以通过编程完成。 步进电机需要一个外部5V电源,该电源应与Raspberry Pi共享一个公共地。 图4显示了如何将步进电机与Raspberry Pi(绿色圆圈)连接。

连接相机 (Connecting camera)

Connecting the camera is the easiest part. The camera port is located near the HDMI connectors. We just need to attach the ribbon cable of the camera firmly, and we are good to go.

连接相机是最简单的部分。 相机端口位于HDMI接口附近。 我们只需要牢固地连接相机的带状电缆即可,我们一切顺利。

Image for post
Image 6: Raspberry Pi layout. Source: Freenove documentation
图6:Raspberry Pi布局 来源:Freenove文档

When all the external components are connected, it will look like the mess on the picture:

连接所有外部组件后,看起来就像图片上的混乱:

Image for post
Image 7: Raspberry Pi with Connected External Components
图像7:具有连接的外部组件的Raspberry Pi

Now when all the components attached to the Raspberry Pi, we can write the python code that will manipulate it.

现在,当所有组件都连接到Raspberry Pi时,我们可以编写将对其进行操作的python代码。

编排软件 (Orchestration software)

We need to write python code that will trigger the Main Pipeline whenever motion is detected. Raspberry Pi has preinstalled the python package RPi.GPIO that provides a class to control the GPIOs. The first thing that we need to do is to set up a GPIO numbering, which defines the schema to address GPIO pins on the Raspberry Pi. Then we set up a pin on which we connected the motion sensor as the input port.

我们需要编写python代码,该代码将在检测到运动时触发主管道。 Raspberry Pi已预安装python软件包RPi.GPIO,该软件包提供了用于控制GPIO的类。 我们需要做的第一件事是设置GPIO编号,该编号定义用于寻址Raspberry Pi上GPIO引脚的架构。 然后设置一个引脚,将运动传感器连接到该引脚上作为输入端口。

import RPi.GPIO as GPIO
import config
# set up BCM GPIO numbering
GPIO.setmode(GPIO.BCM)
# pin of a motion sensor
pin_motion = config.pin_motion # is an integer like "23"
# setup GPIO ports as an input
GPIO.setup(pin_motion, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

After that, we write an event detection method. When a rising edge is detected on the pin_motion, the add_event_detect() will call main_pipeline regardless of whatever else is happening in the program.

之后,我们编写一个事件检测方法。 当在pin_motion上检测到上升沿时,无论程序中发生了什么,add_event_detect()都会调用main_pipeline。

def motion():GPIO.add_event_detect(pin_motion, GPIO.RISING, callback=main_pipeline)return

We need to run the motion detection method in the endless while loop. This way, the program will always be executed unless Keyboard Interrupt ends it.

我们需要在无尽的while循环中运行运动检测方法。 这样,除非键盘中断结束该程序,否则它将始终执行。

try:while True:motion()time.sleep(0.01)
except KeyboardInterrupt:GPIO.cleanup()

Now to the Main Pipeline. The Main Pipeline will call the camera and take the picture. After that, it will try to identify which objects we have on the image: pigeon, human, or nothing. Based on that, it will move the motor, sleep for 180 seconds, or do nothing.

现在到主管道。 主管道将呼叫摄像机并拍照。 之后,它将尝试识别图像上有哪些物体:鸽子,人类或一无所有。 基于此,它将使电动机运动,睡眠180秒或什么也不做。

def main_pipeline(port):
logger("INFO: motion detected")
img = take_pic()predicted_class = inference.predict(img, model)
if predicted_class == 2:logger("INFO: pigeon detected")rotate_motor(rotation_time)if predicted_class == 0:logger("INFO: human detected")time.sleep(180)if predicted_class == 1:logger("INFO: no one detected")
inference.save_image(img, predicted_class)pap_flag = 0
return

We take a picture with a take_pic() method that needs to be specified. First, we configure the camera module:

我们使用需要指定的take_pic()方法拍照。 首先,我们配置相机模块:

import config
from picamera import PiCamera
from datetime import datetime
# initialise camera
camera = PiCamera()
# my camera is flipped, therefore I need to rotate the images
camera.rotation = 180
# get path to store images from the configuration file
image_path = config.image_path

As you might have noticed, I imported config, which is a configuration file in which I specify the GPIO pins for external components, image paths, and the paths to the training data for the image classification model.

您可能已经注意到,我导入了config,这是一个配置文件,在其中我为外部组件,图像路径和图像分类模型的训练数据的路径指定了GPIO引脚。

def take_pic():now = datetime.now()current_time = now.strftime("%m-%d-%Y-%H-%M-%S")camera.start_preview()img_path = image_path + "img-" + current_time + ".jpg"camera.capture(img_path)camera.stop_preview()return img_path

take_pic() takes pictures when a motion was detected and stores it in the img_path specified in the config. If we are still in the data collection stage, the images should be manually labeled with Pigeon Tinder, and the conditional expressions in the Main Pipeline should be commented out until we collected enough images and trained the model.

take_pic()在检测到运动时拍摄照片并将其存储在配置中指定的img_path中。 如果我们仍处于数据收集阶段,则应使用Pigeon Tinder手动标记图像,并应注释掉Main Pipeline中的条件表达式,直到我们收集到足够的图像并训练了模型为止。

If a pigeon was identified on the image, we need to shoo it by rotating the motor. The motor rotation is implemented in the rotate_motor method.

如果在图像上识别出鸽子,我们需要通过旋转马达来射击。 电动机旋转通过rotate_motor方法实现。

Once again, we specify the pins to which the motor is attached. The stepping motor has four pins that are responsible for the rotation angle.

再次,我们指定电动机所连接的引脚。 步进电机有四个销钉,它们负责旋转角度。

# pins of the stepping motor
motor_ports = config.motor_ports # list of pins [12,16,20,21]
# setup GPIO ports as an output
for port in motor_ports:GPIO.setup(port, GPIO.OUT)

The motor rotates at a certain angle (ex. from A to B).

电机旋转一定角度(例如,从A到B)。

Image for post
Image 8: Stepping Motor Diagram. Source: Freenove documentation
图8:步进电机图。 来源:Freenove文档

The pins specified in the code above:[12,16,20,21] correspond to the position of the stepping motor: [A, B, C, D]. For clockwise rotation, we need to iterate over that list in a forward sequence: A→B→C→D→A, etc. Each transition from one state to another (e.g., from A to B) is called a step. By controlling the number of rotation steps, we can control the rotation angle. By controlling the time between two steps, we can control the rotation speed.

上面代码中指定的引脚:[12,16,20,21]对应于步进电机的位置:[A,B,C,D]。 对于顺时针旋转,我们需要按正向顺序遍历该列表:A→B→C→D→A等。从一个状态到另一种状态(例如,从A到B)的每个转换都称为一个步骤。 通过控制旋转步数,我们可以控制旋转角度。 通过控制两个步骤之间的时间,我们可以控制转速。

First, let’s implement a method that would stop the motor:

首先,让我们实现一种使电动机停止的方法:

def stop_motor():global motor_ports
for port in motor_ports:GPIO.output(port, 0)return

We iterate over the motor_ports and set the output level to low. Now we can implement a rotation function that has the same logic: stepwise iteration over the motor_ports and setting up output to high. The rotate_motor() method is slightly more complicated than what we wrote so far.

我们遍历motor_ports并将输出电平设置为低。 现在,我们可以实现一个具有相同逻辑的旋转函数:在motor_ports上进行逐步迭代并将输出设置为high。 rotation_motor()方法比我们到目前为止编写的要复杂一些。

def rotate_motor(rotation_time):"""Rotates the stepping motor:param: rotation_time - interval when motor is rotating in sec. type: int:return:"""global motor_ports# drive_sequence = [[0],[0,1],[1],[1,2],[2],[2,3],[3],[3,0]] #indices of motor portsstop_motor()# define clockwise rotation sequencedrive_sequence = [[0], [1], [2], [3]]current_position = 1drive_delay_ms = 20# define rotation angle# the lower the number, the bigger the angledrive_delay_arc_speed = 0.6start_time = datetime.now()delta_time = 0try:while delta_time < rotation_time:active_motor_indices = drive_sequence[current_position - 1]for port in range(len(motor_ports)):if port in active_motor_indices:GPIO.output(motor_ports[port], 1)else:GPIO.output(motor_ports[port], 0)if drive_delay_ms > 0:current_position += 1else:current_position -= 1if current_position > len(drive_sequence):current_position = 1if current_position == 0:current_position = len(drive_sequence)# drive delay automation partcurr_time = datetime.now()delta_time = (curr_time - start_time).total_seconds()# we want to drive the motor nicely and smoothly to impress the pigeonsdrive_speed = sin(delta_time * drive_delay_arc_speed)drive_delay_ms = 2.0 # 50 is very slow and 2 is the fastestif drive_speed < 0:drive_delay_ms = drive_delay_ms * -1time.sleep(abs(float(drive_delay_ms)) / 1000.0)stop_motor()except KeyboardInterrupt:GPIO.cleanup()return

After the Main Pipeline is ready, we can test our setup:

准备好主管道后,我们可以测试设置:

演示地址

Pigeon Avoidance System. Testing Setup
鸽子回避系统。 测试设置

Note that in this setup, I do not have the model been trained yet. Therefore, the motor runs every time the sensor detects a movement. Also, the plastic cat is not the final solution that is aimed to scare away pigeons. It is here just to indicate that the motor runs.

请注意,在此设置中,我尚未训练模型。 因此,每当传感器检测到运动时,电动机就会运行。 而且,塑料猫不是旨在吓跑鸽子的最终解决方案。 此处仅用于指示电动机正在运行。

生产安装 (Production installation)

Now it’s time to install the Raspberry Pi in the production environment, which is my balcony. To protect the hardware from rain and pigeon attacks, I need waterproof plastic boxes. I ordered beautiful junction boxes on AliExpress. However, I know from my past experiences with shopping shoes and handbags that the delivery might take up to four weeks, and I wanted to start data collection ASAP. Therefore, I used LEGO to build houses for the camera and motion sensor. For the Raspberry itself, I used a Tupperware box, which I, as a good housewife, of course, have in my kitchen.

现在是时候在生产环境中安装Raspberry Pi了,这就是我的阳台。 为了保护硬件免受雨淋和鸽子侵袭,我需要防水的塑料盒。 我在速卖通上订购了漂亮的接线盒。 但是,根据我过去在购物鞋和手袋方面的经验,我知道交货可能需要长达四个星期的时间,因此我想尽快开始收集数据。 因此,我使用乐高积木为摄像机和运动传感器建造房屋。 对于覆盆子本身,我使用了特百惠盒子,作为一个好家庭主妇,我当然把它放在厨房里。

Image for post
Image for post
Image for post
Images 9–11: Data Collection Setup on my Balcony
图片9–11:阳台上的数据收集设置

The next step is to get the Raspberry powered. Initially, it is provided with a power cord, which is about one meter long. That is far from being enough. I do not have a power socket on the balcony. Therefore, I need to power the Raspberry from the outlet inside the house. For that, I soldered a new power cord, which is 5 meters long. With the new wire, I give the power directly to the Raspberry pins, which is usually not recommended, but still is kind of ok.

下一步是使Raspberry供电。 最初,它配有一根电源线,该电源线长约一米。 这还远远不够。 我的阳台上没有电源插座。 因此,我需要从屋内的插座为Raspberry供电。 为此,我焊接了一根5米长的新电源线。 使用新电线,我可以直接给树莓针供电,通常不建议这样做,但还是可以的。

Now is the time to wait for the pigeons. Essentially I need to test how well the motion detector covers my balcony area. Therefore I put oatmeal around my balcony’s perimeter to attract the pigeons and make them walking around. This way, I can check if the motion sensor has dead corners where pigeons can not be detected. After just a few hours, I got the first image of a pigeon!

现在是时候等待鸽子了。 基本上,我需要测试移动探测器覆盖阳台区域的程度。 因此,我把燕麦片放在阳台的周围,以吸引鸽子并使其走动。 这样,我可以检查运动传感器是否有死角,无法检测到鸽子。 短短几个小时后,我得到了第一羽鸽子图像!

Image for post
Image 12: First Pigeon Image
图片12:第一羽鸽子图像

Everyone who has seen this image noticed how fat is the pigeon. Indeed we have very fat pigeons here in Düsseldorf. However, a very unfortunate surprise was that the motion sensor detects pigeons only straight in front of it and ignores the pigeons that are left or right from the sensor. Therefore, I decided to install a second motion sensor that will look into the perpendicular direction. That way, the whole perimeter of my balcony is covered.

看到此图像的每个人都注意到鸽子有多胖。 的确,我们在杜塞尔多夫有非常胖的鸽子。 但是,非常不幸的是,运动传感器仅在其正前方检测到鸽子,而忽略了传感器左侧或右侧的鸽子。 因此,我决定安装第二个垂直于垂直方向的运动传感器。 这样,阳台的整个周边都被覆盖了。

Image for post
Image 13: Motion Sensors Setup
图像13:运动传感器设置

The motion sensors cover two perpendicular edges of my balcony. On the right side of the balcony, I have plants. Therefore pigeons can not land there. To keep things simple, I connected both sensors with the same wire, which sends the signals from both sensors on the same pin. After putting another portion of oatmeal on my balcony, I realized that now the whole balcony is covered, and I am getting way more pigeon pictures then just with the one sensor. Another advantage of a new setup is that I can set the sensitivity of the sensors to the minimum and therefore get less false positives (images without the pigeons which are triggered by the wind moving tree brunches).

运动传感器覆盖了我阳台的两个垂直边缘。 在阳台的右边,我有植物。 因此,鸽子不能在那里降落。 为简单起见,我用同一根导线连接了两个传感器,该传感器从同一引脚上的两个传感器发送信号。 在另一部分燕麦片放在我的阳台上之后,我意识到现在整个阳台都被覆盖了,与仅仅使用一个传感器相比,我获得了更多的鸽子照片。 新设置的另一个优点是,我可以将传感器的灵敏度设置为最小,从而减少误报(没有鸽子的图像是由风树早午餐触发的)。

Now the Pigeon Avoidance System is set up for the data collection. Whenever the sensor detects motion, the camera will take a picture and store it on the Raspberry Pi. Later on, I go through the photos with the Pigeon Tinder and label them for further training.

现在,为数据收集设置了避鸽系统。 每当传感器检测到运动时,相机都会拍照并将其存储在Raspberry Pi中。 后来,我用鸽子火种浏览了照片,并标记了它们以进行进一步的训练。

This is the end of Part 2. In “How to use Deep Learning to shoo the pigeons from the balcony”, I am talking about how to leverage the power of transfer learning for pigeon detection. Stay updated and, in the meantime, a sneak peek from Part 3: How to be taken for a pigeon? Just pretend you are about to build a nest.

这是第2部分的结尾。在“ 如何使用深度学习从阳台上射击鸽子 ”中,我正在谈论如何利用转移学习的力量进行鸽子检测。 保持最新状态,与此同时,还可以偷看第3部分 :如何为鸽子服用? 只是假装您将要筑巢。

Image for post
Image 14: My hand classified as a pigeon.
图片14:我的手被归类为鸽子。

If you got any questions about this project, please feel free to reach me via Linkedin.

如果您对此项目有任何疑问,请随时通过Linkedin与我联系。

翻译自: https://towardsdatascience.com/how-to-set-up-data-collection-for-the-pigeon-avoidance-system-eba572fe6dc9

鸽子为什么喜欢盘旋

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/390535.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端开发-DOM

文档对象模型&#xff08;Document Object Model&#xff0c;DOM&#xff09;是一种用于HTML和XML文档的编程接口。它给文档提供了一种结构化的表示方法&#xff0c;可以改变文档的内容和呈现方式。我们最为关心的是&#xff0c;DOM把网页和脚本以及其他的编程语言联系了起来。…

JAVA-初步认识-第十三章-多线程(验证同步函数的锁)

一. 至于同步函数用的是哪个锁&#xff0c;我们可以验证一下&#xff0c;借助原先卖票的例子 对于程序中的num&#xff0c;从100改为400&#xff0c;DOS的结果显示的始终都是0线程&#xff0c;票号最小都是1。 票号是没有问题的&#xff0c;因为同步了。 有人针对只出现0线程&a…

追求卓越追求完美规范学习_追求新的黄金比例

追求卓越追求完美规范学习The golden ratio is originally a mathematical term. But art, architecture, and design are inconceivable without this math. Everyone aspires to golden proportions as beautiful and unattainable perfection. By visualizing data, we chal…

leetcode 275. H 指数 II

给定一位研究者论文被引用次数的数组&#xff08;被引用次数是非负整数&#xff09;&#xff0c;数组已经按照 升序排列 。编写一个方法&#xff0c;计算出研究者的 h 指数。 h 指数的定义: “h 代表“高引用次数”&#xff08;high citations&#xff09;&#xff0c;一名科研…

leetcode 218. 天际线问题

城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。给你所有建筑物的位置和高度&#xff0c;请返回由这些建筑物形成的 天际线 。 每个建筑物的几何信息由数组 buildings 表示&#xff0c;其中三元组 buildings[i] [lefti, righti, heighti] 表示&#xff1a…

[Android Pro] 终极组件化框架项目方案详解

cp from : https://blog.csdn.net/pochenpiji159/article/details/78660844 前言 本文所讲的组件化案例是基于自己开源的组件化框架项目github上地址github.com/HelloChenJi…其中即时通讯(Chat)模块是单独的项目github上地址github.com/HelloChenJi… 1.什么是组件化&#xff…

leetcode 1818. 绝对差值和

给你两个正整数数组 nums1 和 nums2 &#xff0c;数组的长度都是 n 。 数组 nums1 和 nums2 的 绝对差值和 定义为所有 |nums1[i] - nums2[i]|&#xff08;0 < i < n&#xff09;的 总和&#xff08;下标从 0 开始&#xff09;。 你可以选用 nums1 中的 任意一个 元素来…

【转载】keil5中加入STM32F10X_HD,USE_STDPERIPH_DRIVER的原因

初学STM32&#xff0c;在RealView MDK 环境中使用STM32固件库建立工程时&#xff0c;初学者可能会遇到编译不通过的问题。出现如下警告或错误提示&#xff1a; warning: #223-D: function "assert_param" declared implicitly;assert_param(IS_GPIO_ALL_PERIPH(GPIOx…

剑指 Offer 53 - I. 在排序数组中查找数字 I(二分法)

统计一个数字在排序数组中出现的次数。 示例 1: 输入: nums [5,7,7,8,8,10], target 8 输出: 2 示例 2: 输入: nums [5,7,7,8,8,10], target 6 输出: 0 限制&#xff1a; 0 < 数组长度 < 50000 解题思路 先用二分法查找出其中一个目标元素再向目标元素两边查找…

MVC与三层架构区别

我们平时总是将三层架构与MVC混为一谈&#xff0c;殊不知它俩并不是一个概念。下面我来为大家揭晓我所知道的一些真相。 首先&#xff0c;它俩根本不是一个概念。 三层架构是一个分层式的软件体系架构设计&#xff0c;它可适用于任何一个项目。 MVC是一个设计模式&#xff0c;它…

tensorflow 实现逻辑回归——原以为TensorFlow不擅长做线性回归或者逻辑回归,原来是这么简单哇!...

实现的是预测 低 出生 体重 的 概率。尼克麦克卢尔&#xff08;Nick McClure&#xff09;. TensorFlow机器学习实战指南 (智能系统与技术丛书) (Kindle 位置 1060-1061). Kindle 版本. # Logistic Regression #---------------------------------- # # This function shows ho…

剑指 Offer 66. 构建乘积数组

给定一个数组 A[0,1,…,n-1]&#xff0c;请构建一个数组 B[0,1,…,n-1]&#xff0c;其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 即 B[i]A[0]A[1]…A[i-1]A[i1]…A[n-1]。不能使用除法。 示例: 输入: [1,2,3,4,5] 输出: [120,60,40,30,24] 提示&#xff1a; 所有…

amazeui学习笔记--css(基本样式3)--文字排版Typography

amazeui学习笔记--css&#xff08;基本样式3&#xff09;--文字排版Typography 一、总结 1、字体&#xff1a;amaze默认非 衬线字体&#xff08;sans-serif&#xff09; 2、引用块blockquote和定义列表&#xff1a;引用块blockquote和定义列表&#xff08;dl dt&#xff09;注意…

ELK学习记录三 :elasticsearch、logstash及kibana的安装与配置(windows)

注意事项&#xff1a; 1.ELK版本要求5.X以上 2.Elasticsearch5.x版本必须基于jdk1.8&#xff0c;安装环境必须使用jdk1.8 3.操作系统windows10作为测试环境&#xff0c;其他环境命令有差异&#xff0c;请注意 4.本教程适合完全离线安装 5.windows版本ELK安装包下载路径&#xf…

【quickhybrid】JSBridge的实现

前言 本文介绍quick hybrid框架的核心JSBridge的实现 由于在最新版本中&#xff0c;已经没有考虑iOS7等低版本&#xff0c;因此在选用方案时没有采用url scheme方式&#xff0c;而是直接基于WKWebView实现 交互原理 具体H5和Native的交互原理可以参考前文的H5和Native交互原理 …

面试题 10.02. 变位词组

编写一种方法&#xff0c;对字符串数组进行排序&#xff0c;将所有变位词组合在一起。变位词是指字母相同&#xff0c;但排列不同的字符串。 注意&#xff1a;本题相对原题稍作修改 示例: 输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”], 输出: [ [“ate”,…

智能合约设计模式

2019独角兽企业重金招聘Python工程师标准>>> 设计模式是许多开发场景中的首选解决方案&#xff0c;本文将介绍五种经典的智能合约设计模式并给出以太坊solidity实现代码&#xff1a;自毁合约、工厂合约、名称注册表、映射表迭代器和提款模式。 1、自毁合约 合约自毁…

「CodePlus 2017 12 月赛」火锅盛宴

n<100000种食物&#xff0c;给每个食物煮熟时间&#xff0c;有q<500000个操作&#xff1a;在某时刻插入某个食物&#xff1b;查询熟食中编号最小的并删除之&#xff1b;查询是否有编号为id的食物&#xff0c;如果有查询是否有编号为id的熟食&#xff0c;如果有熟食删除之…

5815. 扣分后的最大得分

给你一个 m x n 的整数矩阵 points &#xff08;下标从 0 开始&#xff09;。一开始你的得分为 0 &#xff0c;你想最大化从矩阵中得到的分数。 你的得分方式为&#xff1a;每一行 中选取一个格子&#xff0c;选中坐标为 (r, c) 的格子会给你的总得分 增加 points[r][c] 。 然…

您有一个上云锦囊尚未领取!

前期&#xff0c;我们通过文章《确认过眼神&#xff1f;上云之路需要遇上对的人&#xff01;》向大家详细介绍了阿里云咨询与设计场景下的五款专家服务产品&#xff0c;企业可以通过这些专家服务产品解决了上云前的痛点。那么&#xff0c;当完成上云前的可行性评估与方案设计后…