Food For Thought!
Crop losses resulting from pests and diseases pose substantial challenges to Indian agriculture, a concern shared globally. However with India's considerable strides in digitization, leveraging AI emerges as a promising solution for swiftly identifying crop issues such as diseases and pests. This technological approach facilitates prompt corrective actions, ensuring enhanced agricultural productivity and sustainability.
AI To the Rescue
Presenting few use cases with examples and working code on how AI can be used with agriculture. This approach uses Gemini and Java with Tools4AI. The complete code is available as opensource for reference and enhancement
We will use various aspects of Tools4AI to convert image into Pojo or JSON and take actions
Pojo
Lets define our Pojo first, I have kept it simple with basic parameters you can add more parameters to it. Please make sure parameter names are meaningful as Tools4AI maps the parameter names dynamically to the AI prompt. '@'Prompt Annotations are optional and can be used within the POJO to give special instructions to Gemini. In this case I am asking Gemini to provide plantType in one of the 4 different categories, also for the healthPercentage I am asking it to give 100% if the crop looks healthy. You can use as many prompt annotation inside Pojo to make it more meaningful if required.
@NoArgsConstructor
@Getter
@Setter
@ToString
public class Plant {
@Prompt(describe ="what type is it CROP or FRUIT or VEGETABLE or FLOWER or TREE or SHRUB or GRASS or WEED or OTHER")
String plantType;
String plantName;
@Prompt(describe ="if it looks healthy then give 100% else give a percentage")
double healthPercentage;
double waterPercentage;
double soilPercentage;
double sunlightPercentage;
double temperature;
boolean hasPest = false;
boolean hasDisease = false;;
boolean hasNutrientDeficiency = false;;
boolean hasWaterDeficiency = false;;
boolean hasSunlightDeficiency = false;;
boolean hasSoilDeficiency = false;;
boolean hasTemperatureDeficiency = false;;
boolean hasFrost = false;;
boolean hasHeatWave = false;;
boolean hasDrought = false;;
boolean hasFlood= false;;
boolean doesItHaveAnyDisease = false;
@Prompt(describe ="based on picture do you think the plant has any disease, if none then return NONE")
String typeOfDisease;
}
The image of the plant will be converted to this Pojo object in real time based on Google Gemini image api. Once its converted to Pojo various actions can be taken by Tools4AI Action Processor.
Example 1
Lets take an image of healthy corn plant
The image can be found here
lets convert this image to Json , you can convert to Pojo as well but for this example I am using JSON . You can add any number of JSON parameter names as you like but keep it meaningful as Tools4AI uses names to map to image
String urlString = "https://raw.githubusercontent.com/spMohanty/PlantVillage-Dataset/master/raw/color/Corn_(maize)___healthy/00031d74-076e-4aef-b040-e068cd3576eb___R.S_HL%208315%20copy%202.jpg";
Url url = new URL(urlString);
String plantDetails = (String) processor.imageToJson(url,
"cropType", "plantName", "healthPercentage",
"waterPercentage", "soilPercentage", "sunlightPercentage",
"temperature", "hasPest", "hasDisease",
"hasNutrientDeficiency", "hasWaterDeficiency",
"hasSunlightDeficiency",
"hasSoilDeficiency",
"hasTemperatureDeficiency",
"hasFrost", "hasHeatWave",
"hasDrought", "hasFlood", "typeOfDisease");
and the result looks like this , as you can see each field provided above has been converted into fieldName and fieldValue , this can also be converted to XML or can be used to make a rest call to another application
starting analysis of healthy corn plant
{"fields":[{"fieldName":"cropType","fieldType":"String","fieldValue":"maize"
},{"fieldName":"plantName","fieldType":"String","fieldValue":"maize"
},{"fieldName":"healthPercentage","fieldType":"String","fieldValue":
"80"},{"fieldName":"waterPercentage","fieldType":"String","fieldValue":"
70"},{"fieldName":"soilPercentage","fieldType":"String","fieldValue":"6
0"},{"fieldName":"sunlightPercentage","fieldType":"String","fieldValue
":"50"},{"fieldName":"temperature","fieldType":"String","fieldValue":"25"
},{"fieldName":"hasPest","fieldType":"String","fieldValue":"false"}
,{"fieldName":"hasDisease","fieldType":"String","fieldValue":"false
"},{"fieldName":"hasNutrientDeficiency","fieldType":"String","fieldVa
lue":"false"},{"fieldName":"hasWaterDeficiency","fieldType":"String","fieldValue
":"false"},{"fieldName":"hasSunlightDeficiency","fieldType":"String","fieldVa
lue":"false"},{"fieldName":"hasSoilDeficiency","fieldType":"String","fieldValue"
:"false"},{"fieldName":"hasTemperatureDeficiency","fieldType":"String","fiel
dValue":"false"},{"fieldName":"hasFrost","fieldType":"String","fieldValue":"false"}
,{"fieldName":"hasHeatWave","fieldType":"String","fieldValue":"fals
e"},{"fieldName":"hasDrought","fieldType":"String","fieldValue":"false
"},{"fieldName":"hasFlood","fieldType":"String","fieldValue":"false"}
,{"fieldName":"typeOfDisease","fieldType":"String","fieldValue":""}
]}
after you convert to Json you can also ask for suggestion
log.info(processor.imageToText(url, "based on image what action should i take on this plant?"));
The response is
The plant is healthy and does not need any action to be taken on it.
Example 2
Lets look at an unhealthy corn Plant
You can find the image here
Lets call Tools4AI processor again with this url
String urlString = "https://raw.githubusercontent.com/spMohanty/PlantVillage-Dataset/master/raw/color/Corn_(maize)___Northern_Leaf_Blight/0079c731-80f5-4fea-b6a2-4ff23a7ce139___RS_NLB%204121.JPG";
Url url = new URL(urlString);
Plant plantDetails = (Plant) processor.imageToPojo(url, Plant.class);
log.info(plantDetails.toString());
As you can see this time we converted it to Pojo object instead of Json , you can chose any format you want either Pojo, JSON or XML or just derive plain string on actions from the image.
The result is
Plant(platType=CROP, plantName=maize, healthPercentage=70.0,
waterPercentage=80.0, soilPercentage=90.0,
sunlightPercentage=100.0, temperature=30.0, hasPest=true,
hasDisease=true, hasNutrientDeficiency=false,
hasWaterDeficiency=false, hasSunlightDeficiency=false,
hasSoilDeficiency=false, hasTemperatureDeficiency=false,
hasFrost=false, hasHeatWave=false, hasDrought=false,
hasFlood=false, doesItHaveAnyDisease=true, typeOfDisease=Leaf
Blight)
and when I ask Gemini for action suggestion
log.info(processor.imageToText(url, "based on image what action
should i take on this plant?"));
The result is
The image shows a corn leaf with symptoms of northern corn leaf
blight. This disease is caused by the fungus Exserohilum turcicum.
The fungus produces toxins that cause the leaves to develop long,
narrow lesions that are tan to brown in color. The lesions may
start out as small, water-soaked spots that later expand and
coalesce. In severe cases, the leaves may dry out and die.
Northern corn leaf blight can cause significant yield losses in
corn.
The beauty of Tools4AI lies in its capability to execute actions based on image descriptions, expanding its functionality as an extensive action model or LLM agent. You can read about it here
For instance, consider the scenario of estimating plant water intake based on forecasted weather. This action can be seamlessly integrated into the prediction list, enhancing adaptability and functionality.
@Log
@Predict
public class WeatherAction {
@Action(description = "get weather for city")
public double getTemperature(String cityName) {
double temperature = 0;
String urlStr = "https://geocoding-api.open-meteo.com/v1/search?name="+cityName+"&count=1&language=en&format=json";
String weatherURlStr = "https://api.open-meteo.com/v1/forecast?latitude=";
try {
StringBuilder response = getResponseFromURl(urlStr);
// Parse JSON response
JSONObject jsonObject = new JSONObject(response.toString());
// Extract latitude and longitude from the JSON response
JSONArray resultsArray = jsonObject.getJSONArray("results");
// Extract latitude and longitude from the first element of the "results" array
if (resultsArray.length() > 0) {
JSONObject result = resultsArray.getJSONObject(0);
double latitude = result.getDouble("latitude");
double longitude = result.getDouble("longitude");
// Print latitude and longitude
log.info("Latitude: " + latitude);
log.info("Longitude: " + longitude);
weatherURlStr = weatherURlStr+latitude+"&longitude="+longitude+"¤t=temperature_2m";
response = getResponseFromURl(weatherURlStr);
log.info(response.toString());
jsonObject = new JSONObject(response.toString());
// Get the "current" object
JSONObject currentObject = jsonObject.getJSONObject("current");
// Extract the temperature value
temperature = currentObject.getDouble("temperature_2m");
// Print the temperature value
log.info("Temperature: " + temperature + " °C");
} else {
log.info("No results found for the longitude and latidue for the city , city is invalid");
}
} catch (Exception e) {
e.printStackTrace();
}
return temperature;
}
Another action example, the CropRecommendationAction class demonstrates an action that recommends a crop based on soil type and climate conditions. By providing inputs for soil type and climate, the action uses predefined rules to suggest an appropriate crop for cultivation. This functionality can be valuable for farmers and agricultural experts seeking guidance on crop selection for optimal yield and sustainability.
@Log
@Predict
public class CropRecommendationAction {
@Action(description = "recommend crop based on soil and climate")
public String recommendCrop(String soilType, String climate) {
String recommendedCrop = "";
// Placeholder for actual implementation
// For demonstration purposes, let's assume simple rules for crop recommendation
if (soilType.equalsIgnoreCase("Loamy") && climate.equalsIgnoreCase("Tropical")) {
recommendedCrop = "Rice";
} else if (soilType.equalsIgnoreCase("Sandy") && climate.equalsIgnoreCase("Dry")) {
recommendedCrop = "Millet";
} else {
recommendedCrop = "Unknown"; // Default recommendation if conditions don't match
}
// Log the recommended crop
log.info("Recommended Crop: " + recommendedCrop);
return recommendedCrop;
}
}
In another example, the LocustControlAction class represents an action designed to control locust attacks based on real-time parameters such as wind speed, wind direction, temperature, and humidity. By analyzing these parameters, the action suggests appropriate measures for mitigating locust infestations, such as spraying pesticides, deploying drones, or closely monitoring the situation. This functionality can assist agricultural authorities and farmers in promptly addressing locust threats to minimize crop damage.
@Log
@Predict
public class LocustControlAction {
@Action(description = "control locust attack based on wind direction and other parameters")
public String controlLocustAttack(double windSpeed, double windDirection, double temperature, double humidity) {
String actionTaken = "";
// Placeholder for actual implementation
// For demonstration purposes, let's assume simple rules for locust control
if (windSpeed > 10 && windDirection >= 180 && windDirection <= 270) {
actionTaken = "Spraying pesticide in the affected area.";
} else if (temperature > 30 && humidity > 70) {
actionTaken = "Deploying drones to disperse locust swarms.";
} else {
actionTaken = "Monitoring the situation closely.";
}
// Log the action taken
log.info("Action Taken: " + actionTaken);
return actionTaken;
}
}
Tools4AI offers versatile applications like the examples provided earlier. It can work with Google Gemini, OpenAI and Anthropic and Since the entire codebase is written in Java, it can be executed on any Java-enabled device, including Android phones. Furthermore, as an open-source project, developers have the opportunity to enhance, contribute to, or share the codebase, fostering collaborative innovation in AI-driven solutions for various domains.
Code for above example is available here