I built a homemade system that automatically intercepts pigeons that fly onto my balcony with a water gun.

While pigeons living in cities are beloved by many, the so-called 'feces pollution' caused by pigeon droppings not only spoils the landscape but also leads to the corrosion and deterioration of buildings, pollutes the living environment, and can even cause health problems such as allergies and infections. Max Nagy, a master's student in computer science at
The overengineered Solution to my Pigeon Problem :: Max Nagy
https://maxnagy.com/posts/pigeons/
Frustrated by the problem of pigeon droppings, Nagy first searched the internet to find common ways to repel pigeons, and compiled his findings into a table.
| How to repel them | Reasons why it's not okay |
|---|---|
| Place a model of a crow | Pigeons get used to it |
| Put a crow sticker on it | Pigeons get used to it |
| Shiny Windmill CD | Pigeons get used to it |
| Animal roars | Pigeons get used to it |
| Dog and cat hair | Pigeons get used to it |
| Ultrasound | Pigeons can't hear |
| Shooting pigeons | It is banned in Germany |
| Keep a cat | The balcony is on the 5th floor so it's dangerous. |
| Bird-repellent spikes | I don't want to put it on the balcony. |
| Bird-proof netting | Unsightly and requires maintenance |
| Drive them away by hand | I can't keep waiting on the balcony |
With this in mind, Nagy wondered, 'Even if it's impossible for humans to keep waiting on balconies, can we outsource this to robots?' The ideas he came up with were summarized as follows:
- Install an electric water gun on the balcony
Detect pigeons with a webcam
- Automatically controls an electric water gun to shoot pigeons
The problem of pigeons getting used to being sprayed with water, a problem that many repelling methods have, can be overcome with this method, since pigeons never get used to being sprayed with water in the first place. It won't ruin the balcony, and most importantly, it won't injure or kill the pigeons. So, I started by purchasing a cheap water gun on Amazon. When I tested it, the range was about 3-4 meters, but it was sufficient for the balcony area. Since the water gun needed to be connected to the internet in order to incorporate it into the interception system, I had to disassemble it first.

I chose

I used an old iPhone 6S as a webcam. I found a suitable spot on the balcony window, created a bracket with a 3D printer, and attached it to the window with double-sided tape . I usedthe iPCamera app to capture the MJPEG stream to detect pigeons.
Now that we have all the hardware, we'll create the software. First, we need to detect the arrival of pigeons using image analysis, so we decided to run a Python script using OpenCV on our laptop to compare a 'normal background image' with the 'current image.' We'll measure the difference for every pixel in the image, and if the average difference exceeds a threshold, we'll determine that a pigeon has arrived. To make the detection more reliable, we'll take the following into consideration.
If the pixel difference is less than 10%, the difference is set to 0 and no change is observed.
If the change is excessively large, ignore the judgment, assuming that someone has touched the camera.
Add a mask to the image to ignore reflections such as flowers blowing in the wind or someone approaching the window.
Once a change is detected, wait until the change disappears.
[code]
stream = CamGear(source='http://IP_OF_IPHONE/live').start()
background = None
while True:
frame = stream.read()
# Apply the mask
frame = cv2.bitwise_and(frame, frame, mask=mask)
# Grayscale conversion
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
if background is None:
background = frame
continue
# Update background
background = cv2.addWeighted(
background, background_alpha, frame, (1 - background_alpha), 0
)
# Calculate the difference between the current image and the background
diff = cv2.absdiff(frame, background)
# Applying thresholds
_, diff = cv2.threshold(diff, 30, 255, cv2.THRESH_BINARY)
score = np.mean(diff)
if armed:
if score > 10:
# The camera was moved
time.sleep(10)
armed = False
elif score > 0.5:
#A pigeon has come!
armed = False
time.sleep(1)
frame = stream.read()
cv2.imwrite(
f'{datetime.now()}.jpg',
frame, # Save the image for later use
)
requests.get('http://IP_OF_SERVER', timeout=1)
else:
# Rerun when the image has settled
armed = (score == 0)
[/code]
In the initial implementation, we used an HTTP server on the Wemos board, which would launch whenever a request was received. However, we discovered an issue where the board's Wi-Fi antenna could not reach the Wi-Fi hotspot at home. As a solution, we decided to connect the board to an iPhone hotspot . However, another issue arose: the Wemos and laptop were connected to different networks, making direct communication impossible.
To fundamentally solve the problem, I decided to stop direct communication between the Wemos board and my laptop and instead create a 'reflector' as a Go program to relay HTTP requests to the Wemos board. In other words, when the reflector receives an HTTP request, it sends a 'PEW!' message to the connected TCP client (i.e., the Wemos board). The only difficult part is properly handling TCP client reconnections, but this can be easily implemented in Go using channels and goroutines . The reflector implementation is as follows:
[code]
func main() {
channel := make(chan byte, 42)
http.HandleFunc('/', func(w http.ResponseWriter, r *http.Request) {
if len(channel) == 0 {
channel <- 42
}
})
go http.ListenAndServe(':4242', nil)
sock, err := net.Listen('tcp', ':4243')
handle(err)
for {
conn, err := sock.Accept()
if err != nil {
continue
}
go func() {
defer conn.Close()
for {
<-channel
_, err = conn.Write([]byte('PEW!\n'))
if err != nil {
break
}
}
}()
}
}
[/code]
The water gun connects via TCP and fires water when it receives the message 'PEW!' The Python script on the laptop remains intact, but the HTTP requests are no longer sent directly to the Wemos board; instead, they are sent to a reflector on the server, which solves the problem. The program that receives messages on the Wemos board was implemented in microPython. While Nagy acknowledges that this snippet does have security issues, he states that it is sufficient for personal use, and that even if a victim were to be harmed, it would be limited to 'dumping 200ml of water on a balcony,' so there is no problem.
[code]
def main():
# Connect to reflector
pin = machine.Pin(5, machine.Pin.OUT)
addr = ('IP_OF_MY_SERVER', 4243)
while True:
s = socket.socket()
s.connect(addr)
try:
while True:
if b'PEW' in s.recv(255):
print('PEW!')
pin.value(1)
time.sleep(0.5)
pin.value(0)
finally:
s.close()
[/code]
The first pigeon to arrive after the automatic interception system was put into operation.

The pigeon was within range of the water gun, but the reflector hadn't been installed at this point, and the water gun's Wi-Fi wasn't picking up the signal properly, so the pigeon escaped. After the reflector was installed and the automatic interception system was fully operational, this was the first time the pigeon had visited, and it was successfully repelled.

However, a few days later, the pigeon returned and escaped the range of the water gun by climbing onto a table that had been left out on the balcony.

Regarding his battle with pigeons, Nagy concluded by saying, 'For now, I'll just keep the table indoors. To be continued.'
Related Posts:







