Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Tanmayee Chalamalasetti
Created March 29, 2023

Weed Detection Drone - AV1

This drone is intended to fly over a field of crops and detect weeds for later removal.

46
Weed Detection Drone - AV1

Things used in this project

Hardware components

Zeee 14.8V 4S Lipo Battery
×1

Software apps and online services

QGroundControl
PX4 QGroundControl
Snappy Ubuntu Core
Snappy Ubuntu Core

Hand tools and fabrication machines

350 Pc. Jumper Wire Kit, 22 AWG
350 Pc. Jumper Wire Kit, 22 AWG
Multitool, Screwdriver
Multitool, Screwdriver
Extraction Tool, 6 Piece Screw Extractor & Screwdriver Set
Extraction Tool, 6 Piece Screw Extractor & Screwdriver Set
Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free
Wire Stripper & Cutter, 18-10 AWG / 0.75-4mm² Capacity Wires
Wire Stripper & Cutter, 18-10 AWG / 0.75-4mm² Capacity Wires
Zip Ties
Adjustable Wrench
Tape, Electrical
Tape, Electrical

Story

Read more

Schematics

Schematic

Code

Main.py

Python
import numpy as np
import cv2
from PIL import Image
import urllib.parse
import urllib.request
import io
import matplotlib.pyplot as plt
from matplotlib import colors
from math import log, exp, tan, atan, pi, ceil
from calculate import distance

#from place_lookup import find_coordinates
#from calc_area import afforestation_area

#300
# deg 0 

def afforestation_area():
    
    img = cv2.imread('weeds1.jpg')
    shifted = cv2.pyrMeanShiftFiltering(img,7,30)
    gray = cv2.cvtColor(shifted, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(gray, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)
    hsv = cv2.cvtColor(shifted,cv2.COLOR_BGR2HSV)

    lower_trees = np.array([10,0,10])
    higher_trees = np.array([180,180,75])

    lower_houses = np.array([90,10,100])
    higher_houses = np.array([255,255,255])

    lower_roads = np.array([90,10,100])
    higher_roads = np.array([100,100,100])

    lower_feilds = np.array([20,20,70])
    higher_feilds = np.array([90,255,255])

    lower_feilds_blue = np.array([0,80,100])
    higher_feilds_blue = np.array([255,250,255])

    masktree = cv2.inRange(hsv,lower_trees,higher_trees)
    maskhouses = cv2.inRange(hsv,lower_houses,higher_houses)
    maskroads = cv2.inRange(hsv,lower_roads,higher_roads)
    maskfeilds_houses = cv2.inRange(hsv,lower_feilds,higher_feilds)
    blue_limiter = cv2.inRange(hsv,lower_feilds_blue,higher_feilds_blue)
    maskfeilds = maskfeilds_houses
    res = cv2.bitwise_and(img,img,mask=maskfeilds)

    gray = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (5,5), 0)
    thresh_img = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

    print(res.shape) # (640, 622, 3)
    print(np.count_nonzero(res)) # 679089

    print("number of pixels", res.size//3)
    tot_pixels = res.size//3
    # print("number of pixels: row x col", res.)

    no_of_non_zero_pixels_rgb =  np.count_nonzero(res)
    row, col, channels = res.shape # 152886
    print("percentage of free land : ", (no_of_non_zero_pixels_rgb/(row*col*channels))) # 0.5686369573954984
    percentage_of_land = no_of_non_zero_pixels_rgb/(row*col*channels)

    # https://www.unitconverters.net/typography/centimeter-to-pixel-x.htm
    # says 1 cm = 37.795275591 pixels
    cm_2_pixel = 37.795275591
    print("row in cm ", row/cm_2_pixel)
    print("col in cm ", col/cm_2_pixel)

    row_cm = row/cm_2_pixel
    col_cm = col/cm_2_pixel
    tot_area_cm = tot_pixels/(row_cm*col_cm)
    tot_area_cm_land = tot_area_cm*percentage_of_land

    print("Total area in cm^2 : ", tot_area_cm_land)

    # in google maps 2.2cm = 50m => 1cm = 22.727272727272727 m in real life at zoom 18
    # 1cm^2 = (22.727272727272727m)^2 = 516.5289256198347 m^2
    print("Total area in m^2 : ", tot_area_cm_land*(516.5289256198347))
    tot_area_m_actual_land = tot_area_cm_land*(516.5289256198347)

    # 1 m^2 = 0.000247105 acres :: source Google
    tot_area_acre_land = tot_area_m_actual_land*0.000247105
    print("Total area in acres : ", tot_area_acre_land)

    # https://www.treeplantation.com/tree-spacing-calculator.html
    # says if you have 2 ft between rows, and 2ft between trees will can take 10890 trees per acre.

    number_of_trees = tot_area_acre_land*10890
    print(f"{round(number_of_trees)} number of trees can be planted in {tot_area_acre_land} acres.")
    
    #show the output image
    true_area = 0 #threshold

    #cnts, _ = cv2.findContours(thresh_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    contours, hierarchy = cv2.findContours(maskfeilds_houses.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    max_area = 0;
    tot_area = 0;

    #tot2_area = cv2.contourArea(contours)
    for cnt in contours:
        area = cv2.contourArea(cnt)
        tot_area += area
        max_area = max(area, max_area)
    #approx = cv2.contourArea(cnt)
        x,y,w,h = cv2.boundingRect(cnt)
        cv2.rectangle(thresh_img,(x,y),(x+w,y+h),(0,255,0),2)

        if(w*h > true_area):
            # true_width = w
            # true_height = h
            # midpoint_x = (x + x + w)/2
            # midpoint_y = (y + y + h)/2
            #cv2.putText(res, "w={},h={}".format(w,h), (x,y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (36,255,12), 2)
            #real_cnt = cnt
            true_area = w*h
            rect = cv2.minAreaRect(cnt)
            box = cv2.boxPoints(rect)
            box = np.int0(box)
            #cv2.drawContours(res,[box],0,(0,0,255),2)
            ((x,y), (width, height), angle) = rect

    print("Max area: " + str(max_area))
    print("Total area: " + str(tot_area))
    #print("Distance to center of contour")
    #print(tot2_area)

    output = cv2.drawContours(res, contours, -1, (0, 0, 255), 3)
    cv2.imshow('res',res)
    cv2.imshow('binary', thresh_img)

    c = max(contours, key = cv2.contourArea)
    x,y,w,h = cv2.boundingRect(c)
    # draw the biggest contour (c) in green
    cv2.rectangle(output,(x,y),(x+w,y+h),(0,255,0),2)
    cv2.putText(res, "w={},h={}".format(w,h), (x,y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36,255,12), 2)
    
    center = "center: (" + str(x+w/2) + ", " + str(y+h/2) + ")"
    cv2.putText(res, center, (int((x+w/2))-50,int((y+h/2))), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36,255,12), 2)
    d = distance(x, y, img.shape[1], img.shape[0], 45, 45, 10)
    print(d)
    print(img.shape[1], img.shape[0])

    cv2.imshow("Output", output)

    # h, s, v = cv2.split(res)
    # fig = plt.figure()
    # axis = fig.add_subplot(1, 1, 1, projection="3d")

    # pixel_colors = img.reshape((np.shape(img)[0]*np.shape(img)[1], 3))
    # norm = colors.Normalize(vmin=-1.,vmax=1.)
    # norm.autoscale(pixel_colors)
    # pixel_colors = norm(pixel_colors).tolist()

    # axis.scatter(h.flatten(), s.flatten(), v.flatten(), facecolors=pixel_colors, marker=".")
    # axis.set_xlabel("Hue")
    # axis.set_ylabel("Saturation")
    # axis.set_zlabel("Value")
    # plt.show()

    cv2.imshow('mask',maskfeilds)
    #cv2.imshow('img', img)

    #cv2.imshow("hsv", hsv)
    cv2.waitKey(delay=0)
    cv2.destroyAllWindows()
    return tot_area_acre_land, round(number_of_trees)
    
print("hi")
afforestation_area()

# if __name__ == "__main__":
#     main()

Calculate.py

Python
Calculates distance between you and the ground
import math as m


def distance(x, y, x_pxls, y_pxls, Hfov, Vfov, dist):

    # x = input("X-coordinate")
    # y = input("Y-coordinate")
    # Hfov = input("Horizontal FOV: ") #constant that will be known
    # Vfov = input("Vertical FOV: ") #constant that will be known
    # dist = input("Altitude: ") #this will be sensor data (in meters)

    #x_pxls = input("X-pixels: ")
    #y_pxls = input("Y-pixels: ")


    w = 2*dist*m.tan(m.degrees(Hfov/2)) #projected width of frame
    h = 2*dist*m.tan(m.degrees(Vfov/2)) #projected height of frame

    p_x = w/x_pxls
    p_y = h/y_pxls

    x_dist = x*p_x - w/2 #x-distance from center
    y_dist = y*p_y - h/2 #y-distance from center

    twoD_dist = m.sqrt(x_dist*x_dist + y_dist*y_dist) #2D distance from center of frame
    threeD_dist = m.sqrt(twoD_dist*twoD_dist + dist*dist) #3D distance to center of camera lens

    return threeD_dist

#x = 45
#print(m.tan(m.radians(x))

Hovergames Repository

Credits

Tanmayee Chalamalasetti

Tanmayee Chalamalasetti

1 project • 0 followers
Thanks to Jason Zhan, Benjamin Li , Ryan Yang, Alan Deng, Justin Shao, Victor Yang, Rishit Gupta, and Christopher Lam.

Comments