³¹¤ËÀ³¤à¥Ï¥È¤Ï¾¯¤Ê¤«¤é¤Ì¿Í¤Ë¤È¤Ã¤Æ°¦¤é¤·¤¤Â¸ºß¤Ç¤¢¤ë°ìÊý¤Ç¡¢¥Ï¥È¤ÎÇÓÝõʪ¤Ë¤è¤Ã¤Æ°ú¤­µ¯¤³¤µ¤ì¤ë¤¤¤ï¤æ¤ë¡Ö¥Õ¥ó³²¡×¤Ïñ¤Ë·Ê´Ñ¤ò»¤Í¤ë¤À¤±¤Ç¤Ê¤¯·ú¤ʪ¤ÎÉå¿©Îô²½¤ò¾·¤¤¤¿¤ê¡¢À¸³è´Ä¶­¤Î±øÀ÷¤ò°ú¤­µ¯¤³¤·¤¿¤ê¡¢¤µ¤é¤Ë¤Ï¥¢¥ì¥ë¥®¡¼¡¦´¶À÷¾É¤È¤¤¤Ã¤¿·ò¹¯Èï³²¤Î¸¶°ø¤Ë¤Ê¤ë¤³¤È¤µ¤¨¤¢¤ê¤Þ¤¹¡£¥«¡¼¥ë¥¹¥ë¡¼¥¨¹©²ÊÂç³Ø¤Î½¤»Î²ÝÄø¤Ç¥³¥ó¥Ô¥å¡¼¥¿¡¼²Ê³Ø¤òÀì¹¶¤¹¤ëMax Nagy»á¤â¼«Âð¤Î¥Ù¥é¥ó¥À¤ËÈôÍ褹¤ë¥Ï¥È¤ËǺ¤Þ¤µ¤ì¤Æ¤¤¤¿°ì¿Í¤Ç¤·¤¿¤¬¡¢Èà¤Ï¥Ï¥È¤ò¼«Æ°·Þ·â¤¹¤ë¥·¥¹¥Æ¥à¤ò¼«ºî¤¹¤ë¤³¤È¤Ç²ò·è¤ò¿Þ¤ê¤Þ¤·¤¿¡£

The overengineered Solution to my Pigeon Problem :: Max Nagy

https://maxnagy.com/posts/pigeons/

¥Ï¥È¤Î¥Õ¥ó³²¤ËÊĸý¤·¤¿Nagy»á¤Ï¤Þ¤º°ìÈÌŪ¤Ê¥Ï¥È¤Î·âÂàÊýË¡¤òÃΤë¤Ù¤¯¥Í¥Ã¥È¸¡º÷¤ò¹Ô¤¤¡¢Ä´ºº·ë²Ì¤òɽ¤Ë¤Þ¤È¤á¤Þ¤·¤¿¡£

·âÂàÊýË¡¥À¥á¤ÊÍýͳ¥«¥é¥¹¤ÎÌÏ·¿¤òÃÖ¤¯¥Ï¥È¤¬´·¤ì¤ë¥«¥é¥¹¤Î¥¹¥Æ¥Ã¥«¡¼¤òޤë¥Ï¥È¤¬´·¤ì¤ë¥Ô¥«¥Ô¥«¤ÎÉ÷¼Ö¡¦CD¥Ï¥È¤¬´·¤ì¤ëưʪ¤¬Ëʤ¨¤ëÀ¼¥Ï¥È¤¬´·¤ì¤ë¥¤¥Ì¤ä¥Í¥³¤ÎÌӥϥȤ¬´·¤ì¤ëͲ»ÇȥϥȤˤÏʹ¤³¤¨¤Ê¤¤¥Ï¥È¤ò·â¤Ä¥É¥¤¥Ä¤Ç¤Ï¶Ø»ß¤µ¤ì¤Æ¤¤¤ë¥Í¥³¤ò»ô¤¦¥Ð¥ë¥³¥Ë¡¼¤Ï5³¬¤Ê¤Î¤Ç´í¸±ËÉÄ»¥¹¥Ñ¥¤¥¯¥Ð¥ë¥³¥Ë¡¼¤ËÃÖ¤­¤¿¤¯¤Ê¤¤ËÉÄ»¥Í¥Ã¥È¸«¤¿Ìܤ¬°­¤¤¾å¤Ë¥á¥ó¥Æ¥Ê¥ó¥¹¤¬É¬Í׿ͤμê¤ÇÄɤ¤Ê§¤¦¥Ð¥ë¥³¥Ë¡¼¤ÇÂÔ¤Á³¤±¤ë¤Î¤Ï̵Íý

¤³¤³¤Þ¤Ç¤Þ¤È¤á¤¿¤È¤³¤í¤ÇNagy»á¤Ï¡Ö¿Í´Ö¤¬¥Ð¥ë¥³¥Ë¡¼¤ÇÂÔ¤Á³¤±¤ë¤Î¤Ï̵Íý¤À¤È¤·¤Æ¤â¡¢¥í¥Ü¥Ã¥È¤Ë¥¢¥¦¥È¥½¡¼¥·¥ó¥°¤Ç¤­¤ë¤Î¤Ç¤Ï¤Ê¤¤¤«¡©¡×¤È¹Í¤¨¤Þ¤·¤¿¡£»×¤¤¤Ä¤¤¤¿¥¢¥¤¥Ç¥¢¤òÀ°Íý¤¹¤ë¤È°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ê¤Þ¤·¤¿¡£

¡¦¥Ð¥ë¥³¥Ë¡¼¤ËÅÅÆ°¿åŴˤ¤òÀßÃÖ¤¹¤ë

¡¦¥¦¥§¥Ö¥«¥á¥é¤Ç¥Ï¥È¤ò¸¡ÃΤ¹¤ë

¡¦¼«Æ°Åª¤ËÅÅÆ°¿åŴˤ¤òÁàºî¤·¤Æ¥Ï¥È¤ò·â¤Ä

¿¤¯¤Î·âÂàÊýË¡¤Ç²ÝÂê¤À¤Ã¤¿¡Ö¥Ï¥È¤¬´·¤ì¤ë¡×ÌäÂê¤Ë¤Ä¤¤¤Æ¤â¡¢¤½¤â¤½¤â¥Ï¥È¤¬¿å¤ò³Ý¤±¤é¤ì¤ë¤³¤È¤Ë´·¤ì¤ë¤³¤È¤Ï¤¢¤êÆÀ¤Ê¤¤¤Î¤Ç¥¯¥ê¥¢¤Ç¤­¤Þ¤¹¡£¥Ð¥ë¥³¥Ë¡¼¤òÂæÌµ¤·¤Ë¤¹¤ë¤³¤È¤â¤¢¤ê¤Þ¤»¤ó¤·¡¢²¿¤è¤ê¥Ï¥È¤ò½ý¤Ä¤±¤¿¤ê»¦¤·¤¿¤ê¤¹¤ë¤³¤È¤¬¤¢¤ê¤Þ¤»¤ó¡£¤½¤³¤Ç¤Þ¤º¤ÏAmazon¤Ë¤Æ°Â¤¤¿åŴˤ¤ò¹ØÆþ¤·¤Þ¤·¤¿¡£»î¤··â¤Á¤·¤¿¤È¤³¤í¼ÍÄøµ÷Î¥¤Ï3¡Á4¥á¡¼¥È¥ëÄøÅ٤Ǥ·¤¿¤¬¡¢¥Ð¥ë¥³¥Ë¡¼¤ÎÈϰϤʤ齽ʬ¤Ç¤·¤¿¡£·Þ·â¥·¥¹¥Æ¥à¤ËÁȤ߹þ¤à¤Ë¤Ï¿åŴˤ¤ò¥¤¥ó¥¿¡¼¥Í¥Ã¥È¤ËÀܳ¤¹¤ëɬÍפ¬¤¢¤ë¤¿¤á°ìö¿åŴˤ¤òʬ²ò¤·¤Þ¤·¤¿¡£



¿åŴˤ¤òÀ©¸æ¤¹¤ë¤¿¤á¤Î´ðÈפˤÏWemos D1 Mini¤òÁªÂò¤·¤Þ¤·¤¿¡£¾®·¿¤Ç°Â²Á¤Ç¤¢¤ë¾å¤ËWi-Fi¤âÅëºÜ¤·¤Æ¤¤¤Þ¤¹¡£¥ê¥ì¡¼¥·¡¼¥ë¥É¤òÄɲ乤뤳¤È¤ÇÅŸ»¤ÎÀ©¸æ¤¬¤Ç¤­¤ë¤è¤¦¤Ë¤·¡¢µëÅÅÍѤÎUSB¥±¡¼¥Ö¥ë¤òÄ̤¹·ê¤òËÜÂΤ˳«¤±¤Þ¤·¤¿¡£



¥¦¥§¥Ö¥«¥á¥é¤Ë¤Ï¸Å¤¤iPhone 6S¤òήÍѤ·¤Þ¤·¤¿¡£¥Ù¥é¥ó¥À¤ËÌ̤·¤¿Áë¤ÎŬÅö¤Ê°ÌÃÖ¤ò¸«¤Ä¤±¤Æ¸ÇÄêÍѤΥ֥饱¥Ã¥È¤ò3D¥×¥ê¥ó¥¿¡¼¤ÇºîÀ®¤·¡¢Î¾Ì̥ơ¼¥×¤ÇÁë¤ËÀßÃÖ¡£¥Ï¥È¤ò¸¡ÃΤ¹¤ë¤¿¤á¤ËiPCamera¥¢¥×¥ê¤ÇMJPEG¥¹¥È¥ê¡¼¥à¤ò¼èÆÀ¤·¤Þ¤¹¡£

¥Ï¡¼¥É¥¦¥§¥¢¤Ï¤½¤í¤Ã¤¿¤Î¤Ç¼¡¤Ï¥½¥Õ¥È¥¦¥§¥¢¤òºîÀ®¤·¤Þ¤¹¡£¤Þ¤º¤Ï¥Ï¥È¤ÎÈôÍè¤ò²èÁü²òÀϤǸ¡ÃΤ¹¤ëɬÍפ¬¤¢¤ë¤¿¤á¡¢¥Î¡¼¥È¥Ñ¥½¥³¥ó¤ÇOpenCV¤ò»È¤Ã¤¿Python¥¹¥¯¥ê¥×¥È¤ò¼Â¹Ô¤·¤Æ¡ÖÄ̾ï¤ÎÇØ·Ê²èÁü¡×¤È¡Ö¸½ºß¤Î²èÁü¡×¤òÈæ³Ó¤¹¤ë¤³¤È¤Ë¤·¤Þ¤·¤¿¡£²èÁü¤ÎÁ´¥Ô¥¯¥»¥ë¤Ë¤Ä¤¤¤Æº¹Ê¬¤ò¬Äꤷ¡¢º¹Ê¬¤ÎÊ¿¶ÑÃͤ¬ïçÃͤòͤ¨¤¿¾ì¹ç¤Ë¥Ï¥È¤¬Í褿¤ÈȽÄꤹ¤ë¤ï¤±¤Ç¤¹¡£¤è¤êȽÄê¤Ë³Î¼ÂÀ­¤ò»ý¤¿¤»¤ë¤¿¤á°Ê²¼¤ò¹Íθ¤¹¤ë¤è¤¦¤Ë¤·¤Þ¤¹¡£

¡¦¥Ô¥¯¥»¥ë¤Îº¹Ê¬¤¬10%̤Ëþ¤Ê¤é¡¢º¹Ê¬0¤È¤·¤ÆÊѲ½¤Ê¤·¤È°·¤¦

¡¦ÊѲ½Î̤¬²á¾ê¤ËÂ礭¤¤¾ì¹ç¤Ï¡¢Ã¯¤«¤¬¥«¥á¥é¤Ë¿¨¤ì¤¿¤â¤Î¤È¤·¤ÆÈ½Äê¤ò̵»ë¤¹¤ë

¡¦É÷¤ËÍɤì¤ë²Ö¤ä狼¤¬Áë¤Ë¶á¤Å¤¤¤¿ºÝ¤Î¼Ì¤ê¹þ¤ß¤ò̵»ë¤¹¤ë¤è¤¦¡¢²èÁü¤Ë¥Þ¥¹¥¯¤òÄɲ乤ë

¡¦°ìöÊѲ½¤ò¸¡½Ð¤·¤¿¸å¤Ï¡¢ÊѲ½¤¬¤Ê¤¯¤Ê¤ë¤Þ¤ÇÂÔµ¡¤¹¤ë

stream = CamGear(source="http://IP_OF_IPHONE/live").start()

background = None
while True:
frame = stream.read()
# ¥Þ¥¹¥¯¤òŬÍѤ¹¤ë
frame = cv2.bitwise_and(frame, frame, mask=mask)

# ¥°¥ì¥¤¥¹¥±¡¼¥ëÊÑ´¹
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)

if background is None:
background = frame
continue

# ÇØ·Ê¤Î¹¹¿·
background = cv2.addWeighted(
background, background_alpha, frame, (1 - background_alpha), 0
)

# ¸½ºß¤Î²èÁü¤ÈÇØ·Ê¤È¤Îº¹Ê¬¤òµá¤á¤ë
diff = cv2.absdiff(frame, background)

# ïçÃͤÎŬÍÑ
_, diff = cv2.threshold(diff, 30, 255, cv2.THRESH_BINARY)

score = np.mean(diff)
if armed:
if score > 10:
# ¥«¥á¥é¤¬Æ°¤«¤µ¤ì¤¿
time.sleep(10)
armed = False
elif score > 0.5:
# ¥Ï¥È¤¬Í褿¡ª
armed = False
time.sleep(1)
frame = stream.read()
cv2.imwrite(
f"{datetime.now()}.jpg",
frame, # ¸å¤Ç»ÈÍѤ¹¤ë¤¿¤á¤Ë²èÁü¤òÊݸ¤¹¤ë
)

requests.get("http://IP_OF_SERVER", timeout=1)

else:
# ²èÁü¤¬Íî¤ÁÃ夤¤¿¤éºÆ¼Â¹Ô¤¹¤ë
armed = (score == 0)

ºÇ½é¤Î¼ÂÁõ¤Ç¤ÏWemos¥Ü¡¼¥É¾å¤ÎHTTP¥µ¡¼¥Ð¡¼¤ò»ÈÍѤ·¥ê¥¯¥¨¥¹¥È¤ò¼õ¿®¤¹¤ë¤¿¤Ó¤Ëµ¯Æ°¤¹¤ëÊýË¡¤òºÎÍѤ·¤Æ¤¤¤Þ¤·¤¿¡£¤·¤«¤·¤Ê¤¬¤é¥Ü¡¼¥É¤ÎWi-Fi¥¢¥ó¥Æ¥Ê¤Ç¤Ï¼«Âð¤ÎWi-Fi¥¹¥Ý¥Ã¥È¤Þ¤ÇÅÅÇȤ¬ÆÏ¤«¤Ê¤¤¤È¤¤¤¦ÌäÂ꤬ȯ³Ð¡£²ò·èºö¤È¤·¤Æ¥Ü¡¼¥É¤òiPhone¤Î¥Û¥Ã¥È¥¹¥Ý¥Ã¥È¤ËÀܳ¤¹¤ë¤³¤È¤Ë¤·¤Þ¤·¤¿¡£¤¿¤À¡¢Wemos¤È¥Î¡¼¥È¥Ñ¥½¥³¥ó¤¬Ê̤Υͥåȥ¥¯¤ËÀܳ¤µ¤ì¤Æ¤·¤Þ¤¤Ä¾ÀÜÄÌ¿®¤Ç¤­¤Ê¤¯¤Ê¤ë¤È¤¤¤¦Ê̤ÎÌäÂ꤬ȯÀ¸¡£

ÌäÂê¤òº¬ËÜŪ¤Ë²ò·è¤¹¤ë¤¿¤á¤ËWemos¥Ü¡¼¥É¤È¥Î¡¼¥È¥Ñ¥½¥³¥ó¤òľÀܤ¹¤ë¤Î¤ò¤ä¤á¡¢Wemos¥Ü¡¼¥É¤ØHTTP¥ê¥¯¥¨¥¹¥È¤ò¥ê¥ì¡¼¤¹¤ë¤¿¤á¤Î¡Ö¥ê¥Õ¥ì¥¯¥¿¡¼¡×¤òGo¥×¥í¥°¥é¥à¤È¤·¤ÆºîÀ®¤¹¤ë¤³¤È¤Ë¡£¤Ä¤Þ¤ê¡¢HTTP¥ê¥¯¥¨¥¹¥È¤ò¥ê¥Õ¥ì¥¯¥¿¡¼¤¬¼õ¿®¤¹¤ë¤ÈÀÜÂ³Ãæ¤ÎTCP¥¯¥é¥¤¥¢¥ó¥È(¤Ä¤Þ¤êWemos¥Ü¡¼¥É)¤Ë¡ÖPEW!¡×¤È¤¤¤¦¥á¥Ã¥»¡¼¥¸¤òÁ÷¿®¤¹¤ë¤ï¤±¤Ç¤¹¡£Í£°ìÆñ¤·¤¤¤Î¤ÏTCP¥¯¥é¥¤¥¢¥ó¥È¤ÎºÆÀܳ¤òŬÀڤ˽èÍý¤¹¤ë¤È¤³¤í¤Ç¤¹¤¬¡¢Go¸À¸ì¤Ê¤é¥Á¥ã¥Í¥ë¤È¥´¥ë¡¼¥Á¥ó¤ò»È¤¨¤Ð´Êñ¤Ë¼ÂÁõ¤Ç¤­¤Þ¤¹¡£¥ê¥Õ¥ì¥¯¥¿¡¼¤Î¼ÂÁõ¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¹¡£

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!
"))
if err != nil {
break
}
}
}()
}
}

¿åŴˤ¤ÏTCP·Ðͳ¤ÇÀܳ¤·¡ÖPEW!¡×¤È¤¤¤¦¥á¥Ã¥»¡¼¥¸¤ò¼õ¿®¤¹¤ë¤È¿å¤òȯ¼Í¤·¤Þ¤¹¡£¥Î¡¼¥È¥Ñ¥½¥³¥ó¤ÎPython¥¹¥¯¥ê¥×¥È¤Ï¤½¤Î¤Þ¤Þ»Ä¤·¡¢HTTP¥ê¥¯¥¨¥¹¥È¤òWemos¥Ü¡¼¥É¤ËľÀÜÁ÷¿®¤·¤Æ¤¤¤¿¤Î¤ò¤ä¤á¤Æ¡¢Âå¤ï¤ê¤Ë¥µ¡¼¥Ð¡¼¾å¤Î¥ê¥Õ¥ì¥¯¥¿¡¼¤ËÁ÷¿®¤¹¤ì¤ÐËü»ö²ò·è¤È¤Ê¤ê¤Þ¤¹¡£Wemos¥Ü¡¼¥É¤Ç¥á¥Ã¥»¡¼¥¸¤ò¼õ¤±¼è¤ë¥×¥í¥°¥é¥à¤ÏmicroPython¤Ç¼ÂÁõ¤·¤Þ¤·¤¿¡£¤Ê¤ª¡¢Nagy»á¤Ï¤³¤Î¥¹¥Ë¥Ú¥Ã¥È¤Ë¤Ï¥»¥­¥å¥ê¥Æ¥£¾å¤ÎÌäÂ꤬¤¢¤ë¤³¤È¤òǧ¤á¤¿¾å¤Ç¸Ä¿ÍŪ¤Ê»ÈÍÑÌÜŪ¤Ë¤Ï½½Ê¬¤Ç¤¢¤ë¤È¤·¡¢¤¿¤È¤¨Èï³²¤Ë¤¢¤Ã¤¿¤È¤·¤Æ¤â¡Ö200ml¤â¤Î¿å¤ò¥Ð¥ë¥³¥Ë¡¼¤Ë¼Î¤Æ¤Æ¤·¤Þ¤¦¤è¤¦¤Ê¤³¤È¡×¤Ç¼ý¤Þ¤ë¤¿¤á°ì±þÌäÂê¤Ê¤·¤È¤·¤Æ¤¤¤Þ¤¹¡£

def main():
# ¥ê¥Õ¥ì¥¯¥¿¡¼¤ËÀܳ
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()

¼«Æ°·Þ·â¥·¥¹¥Æ¥à¤¬²ÔƯ¤·¤ÆºÇ½é¤ËÈôÍ褷¤¿¥Ï¥È¡£



¥Ï¥È¤Ï¿åŴˤ¤Î¼ÍÄøÈÏ°ÏÆâ¤Ë¤¤¤Þ¤¹¤¬¡¢¤³¤Î»þÅÀ¤Ç¤Ï¥ê¥Õ¥ì¥¯¥¿¡¼¤¬Æ³Æþ¤µ¤ì¤Æ¤ª¤é¤º¿åŴˤ¤ÎWi-Fi¤¬¿®¹æ¤ò¤¦¤Þ¤¯½¦¤¨¤Æ¤¤¤Ê¤«¤Ã¤¿¤¿¤á¥Ï¥È¤ÏÆñ¤òƨ¤ì¤Æ¤¤¤Þ¤¹¡£¥ê¥Õ¥ì¥¯¥¿¡¼¤òƳÆþ¤·¤Æ¼«Æ°·Þ·â¥·¥¹¥Æ¥à¤¬´°Á´¤Ëµ¡Ç½¤¹¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ½é¤á¤ÆË¬Ì䤷¤Æ¤­¤¿¥Ï¥È¤Ï¡¢½é¤Î·âÂà¤ËÀ®¸ù¤·¤¿¤È¤Î¤³¤È¡£



¤¿¤À¤·¡¢¤µ¤é¤Ë¿ôÆü¸å¤Ë¸½¤ì¤¿¥Ï¥È¤Ï¥Ð¥ë¥³¥Ë¡¼¤Ë½Ð¤·¤Ã¤Ñ¤Ê¤·¤Ë¤·¤Æ¤¤¤¿¥Æ¡¼¥Ö¥ë¤Ë¾å¤ë¤³¤È¤Ç¿åŴˤ¤Î¼ÍÄø¤òƨ¤ì¤Æ¤·¤Þ¤¤¤Þ¤·¤¿¡£



Nagy»á¤Ï¥Ï¥È¤È¤Î¹¶ËɤˤĤ¤¤Æ¡Ö¤È¤ê¤¢¤¨¤º¥Æ¡¼¥Ö¥ë¤Ï¼¼Æâ¤ËÃÖ¤¯¤è¤¦¤Ë¤·¤Þ¤¹¡£¤Ä¤Å¤¯¡×¤ÈÄù¤á¤¯¤¯¤ê¤Þ¤·¤¿¡£