diff --git a/agro-quiz-app/components.json b/agro-quiz-app/components.json index 4d01f8ba..78e471c8 100644 --- a/agro-quiz-app/components.json +++ b/agro-quiz-app/components.json @@ -4,14 +4,14 @@ "rsc": true, "tsx": true, "tailwind": { - "config": "tailwind.config.js", - "css": "src/app/globals.css", + "config": "./tailwind.config.js", + "css": "./src/app/globals.css", "baseColor": "slate", "cssVariables": true, "prefix": "" }, "aliases": { - "components": "@/components", - "utils": "@/lib/utils" + "@components": "./src/components", + "@utils": "./src/lib/utils" } -} \ No newline at end of file +} diff --git a/agro-quiz-app/next.config.js b/agro-quiz-app/next.config.js index 767719fc..bf2b145c 100644 --- a/agro-quiz-app/next.config.js +++ b/agro-quiz-app/next.config.js @@ -1,4 +1,14 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {} - -module.exports = nextConfig +const nextConfig = { + reactStrictMode: true, // Enables React strict mode + swcMinify: true, // Enables SWC-based minification for faster builds and smaller bundle sizes + images: { + domains: ['example.com'], // Allow images from specific domains + }, + experimental: { + appDir: true, // Enables the new Next.js app directory (for Next.js 13+) + }, + }; + + module.exports = nextConfig; + \ No newline at end of file diff --git a/agro-quiz-app/package.json b/agro-quiz-app/package.json index 0c8b950f..0210f452 100644 --- a/agro-quiz-app/package.json +++ b/agro-quiz-app/package.json @@ -14,23 +14,23 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "lucide-react": "^0.303.0", - "next": "14.0.4", - "react": "^18", - "react-dom": "^18", + "next": "^14.0.4", + "react": "^18.2.0", + "react-dom": "^18.2.0", "react-icons": "^4.12.0", "react-toastify": "^9.1.3", "tailwind-merge": "^2.2.0", "tailwindcss-animate": "^1.0.7" }, "devDependencies": { - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", - "autoprefixer": "^10.0.1", - "eslint": "^8", - "eslint-config-next": "14.0.4", - "postcss": "^8", + "@types/node": "^20.0.0", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "autoprefixer": "^10.4.0", + "eslint": "^8.50.0", + "eslint-config-next": "^14.0.4", + "postcss": "^8.4.0", "tailwindcss": "^3.3.0", - "typescript": "^5" + "typescript": "^5.0.0" } } diff --git a/agro-quiz-app/postcss.config.js b/agro-quiz-app/postcss.config.js index 33ad091d..c4a2b144 100644 --- a/agro-quiz-app/postcss.config.js +++ b/agro-quiz-app/postcss.config.js @@ -1,6 +1,8 @@ module.exports = { plugins: { + // Tailwind CSS integration tailwindcss: {}, + // Adds vendor prefixes for cross-browser compatibility autoprefixer: {}, }, -} +}; diff --git a/agro-quiz-app/tailwind.config.js b/agro-quiz-app/tailwind.config.js index 7cb7e37a..301ecaf2 100644 --- a/agro-quiz-app/tailwind.config.js +++ b/agro-quiz-app/tailwind.config.js @@ -7,7 +7,6 @@ module.exports = { './app/**/*.{ts,tsx}', './src/**/*.{ts,tsx}', ], - prefix: "", theme: { container: { center: true, @@ -74,4 +73,4 @@ module.exports = { }, }, plugins: [require("tailwindcss-animate")], -} \ No newline at end of file +}; diff --git a/agro-quiz-app/tailwind.config.ts b/agro-quiz-app/tailwind.config.ts index 1af3b8f0..af9aa7a9 100644 --- a/agro-quiz-app/tailwind.config.ts +++ b/agro-quiz-app/tailwind.config.ts @@ -18,3 +18,4 @@ const config: Config = { plugins: [], } export default config + diff --git a/agro-quiz-app/tsconfig.json b/agro-quiz-app/tsconfig.json index e59724b2..39098f9f 100644 --- a/agro-quiz-app/tsconfig.json +++ b/agro-quiz-app/tsconfig.json @@ -18,8 +18,9 @@ "name": "next" } ], + "baseUrl": "./", "paths": { - "@/*": ["./src/*"] + "@/*": ["src/*"] } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], diff --git a/agrotech-ai-apis/app.py b/agrotech-ai-apis/app.py index 7d9ce82d..9e85d4a9 100644 --- a/agrotech-ai-apis/app.py +++ b/agrotech-ai-apis/app.py @@ -19,37 +19,32 @@ soil_lab_prompt = ( "As an expert in location-based services and geospatial data, your task is to provide a precise and accurate list of nearby soil testing labs " "for the specified location. Please return the response in a well-structured JSON format. " - "Each entry should include the lab's name, latitude, longitude, and a direct Google Maps link for easy navigation. " + "Each entry should include the lab's name, latitude, longitude, and a direct Google Maps link for easy navigation." ) ee_shop_prompt = ( "As an expert in location-based services and geospatial data, your task is to provide a precise and accurate list of nearby electrical and electronics shops " "for the specified location. Please return the response in a well-structured JSON format. " - "Each entry should include the shop's name, latitude, longitude, and a direct Google Maps link for easy navigation. " + "Each entry should include the shop's name, latitude, longitude, and a direct Google Maps link for easy navigation." ) # Initialize Flask app app = Flask(__name__) CORS(app) -# Function to load Gemini Pro model and get responses +# Load Gemini Pro model model = genai.GenerativeModel("gemini-pro") chat = model.start_chat(history=[]) def extract_json(text): json_pattern = r'\{.*\}|\[.*\]' match = re.search(json_pattern, text, re.DOTALL) - if match: - return match.group(0) - return None + return match.group(0) if match else None def get_gemini_response(location, prompt): - full_prompt = prompt + location + full_prompt = f"{prompt} {location}" response = chat.send_message(full_prompt, stream=True) - response_text = "" - for chunk in response: - response_text += chunk.text - return response_text + return ''.join(chunk.text for chunk in response) # API route to get soil testing labs based on location @app.route('/find_soil_labs', methods=['POST']) @@ -68,8 +63,7 @@ def find_soil_labs(): return jsonify(soil_labs), 200 except json.JSONDecodeError: return jsonify({"error": "Error decoding the JSON data."}), 500 - else: - return jsonify({"error": "No valid JSON found in the response."}), 500 + return jsonify({"error": "No valid JSON found in the response."}), 500 # API route to get nearby electrical and electronics shops based on location @app.route('/find_ee_shops', methods=['POST']) @@ -88,8 +82,7 @@ def find_ee_shops(): return jsonify(ee_shops), 200 except json.JSONDecodeError: return jsonify({"error": "Error decoding the JSON data."}), 500 - else: - return jsonify({"error": "No valid JSON found in the response."}), 500 + return jsonify({"error": "No valid JSON found in the response."}), 500 # API route to check mushroom edibility @app.route("/mushroom_edibility", methods=["POST"]) @@ -98,32 +91,29 @@ def mushroom_edibility(): # API route to recommend crops based on soil and previous crop information @app.route('/crop_recommendation', methods=['POST']) -def crop_recommendation(): +def crop_recommendation_route(): + data = request.json + if not data: + return jsonify({'error': 'No data provided'}), 400 + try: - data = request.json print("Received data:", data) # Debugging: Log received data - - # Call the crop recommendation function result = recommend_crop(data) return jsonify(result), 200 - except Exception as e: return jsonify({'error': str(e)}), 500 # API route for seed quality prediction @app.route('/predict_seed_quality', methods=['POST']) def predict_seed_quality_route(): - """API endpoint for predicting seed quality.""" if 'file' not in request.files: return jsonify({'error': 'No file provided'}), 400 file = request.files['file'] - if not file: return jsonify({'error': 'No file provided'}), 400 try: - # Call the seed quality prediction function result = predict_seed_quality(file) return jsonify(result), 200 except Exception as e: @@ -136,7 +126,6 @@ def predict(): return jsonify({"error": "No image part in the request"}), 400 file = request.files['image'] - if file.filename == '': return jsonify({"error": "No image selected for uploading"}), 400 @@ -148,11 +137,7 @@ def predict(): return jsonify({"error": "Prediction failed"}), 500 class_name = get_class_name(result_index) - if class_name: - return jsonify({"prediction": class_name}), 200 - else: - return jsonify({"error": "Invalid class index returned."}), 500 - + return jsonify({"prediction": class_name}), 200 if class_name else jsonify({"error": "Invalid class index returned."}), 500 except Exception as e: print(f"Error in /predict: {e}") return jsonify({"error": "An error occurred during prediction"}), 500 diff --git a/agrotech-ai-apis/crop_recommendation.py b/agrotech-ai-apis/crop_recommendation.py index 3eae969f..44fb6cd1 100644 --- a/agrotech-ai-apis/crop_recommendation.py +++ b/agrotech-ai-apis/crop_recommendation.py @@ -45,8 +45,8 @@ def recommend_crop(data): # Prepare data for prediction input_data = pd.DataFrame([{ - "Previous Crop": previous_crop_mapping.get(previous_crop, -1), # Map to integer - "Soil Type": soil_type_mapping.get(soil_type, -1), # Map to integer + "Previous Crop": previous_crop_mapping.get(previous_crop, -1), # Map to integer or -1 if not found + "Soil Type": soil_type_mapping.get(soil_type, -1), # Map to integer or -1 if not found "Moisture Level": moisture_level, "Nitrogen (N)": nitrogen, "Phosphorus (P)": phosphorus, @@ -56,10 +56,8 @@ def recommend_crop(data): # Make prediction prediction = crop_model.predict(input_data) - if prediction[0] in crop_mapping: - recommended_crop = crop_mapping[prediction[0]] - else: - return {'Recommended Crop': 'No prediction available'} + # Map prediction to crop name + recommended_crop = crop_mapping.get(prediction[0], 'No prediction available') return {'Recommended Crop': str(recommended_crop)} diff --git a/agrotech-ai-apis/mushroom_edibility.py b/agrotech-ai-apis/mushroom_edibility.py index b006e90c..f66b4e2b 100644 --- a/agrotech-ai-apis/mushroom_edibility.py +++ b/agrotech-ai-apis/mushroom_edibility.py @@ -31,35 +31,37 @@ def check_mushroom_edibility(): } data_dict = {} - for key, mapping in mappings.items(): value = request.form.get(key) if value: mapped_value = mapping.get(value) data_dict[key] = [mapped_value if mapped_value is not None else None] else: - raise ValueError(f"Missing value in column: {key} with value {value}") data_dict[key] = [None] df = pd.DataFrame(data_dict) + # Load encoders with open('./models/encoders.pkl', 'rb') as f: encoders = pickle.load(f) + # Transform using encoders for col in df.columns: if col in encoders: if df[col].isnull().any(): raise ValueError(f"Missing value in column: {col}") df[col] = encoders[col].transform(df[col]) - return jsonify({"edibility": edibility_check(df)}) + # Get edibility prediction + edibility_result = edibility_check(df) + return jsonify({"edibility": edibility_result}) except Exception as e: return jsonify({"error": str(e)}) - def edibility_check(df): with open("./models/model.pkl", "rb") as f: model = pickle.load(f) + prediction = model.predict(df) return "Edible" if prediction[0] == 1 else "Poisonous" diff --git a/agrotech-ai-apis/paddy_prediction.py b/agrotech-ai-apis/paddy_prediction.py index c847708e..0d65d37e 100644 --- a/agrotech-ai-apis/paddy_prediction.py +++ b/agrotech-ai-apis/paddy_prediction.py @@ -10,8 +10,10 @@ model = load_model('models/rice_model.h5', compile=False) # Class labels for the paddy diseases -modified_class_label = ['Bacterial Leaf Blight', 'Bacterial Leaf Streak', 'Bacterial Panicle Blight', 'Blast', - 'Brown Spot', 'Dead Heart', 'Downy Mildew', 'Hispa', 'Normal', 'Tungro'] +modified_class_label = [ + 'Bacterial Leaf Blight', 'Bacterial Leaf Streak', 'Bacterial Panicle Blight', 'Blast', + 'Brown Spot', 'Dead Heart', 'Downy Mildew', 'Hispa', 'Normal', 'Tungro' +] LABEL_DESCRIPTION = [ { @@ -87,25 +89,31 @@ ] def preprocess_image(image_path, target_size=(256, 256)): + """Load and preprocess the image for prediction.""" img = load_img(image_path, target_size=target_size) img_array = img_to_array(img) img_array = np.expand_dims(img_array, axis=0) img_array = tf.cast(img_array / 255.0, tf.float32) return img_array -def predict_paddy(filepath): - predictions = model.predict(preprocess_image(filepath)) +def predict_paddy(image_path): + """Predict the class of the paddy image.""" + processed_image = preprocess_image(image_path) + predictions = model.predict(processed_image) predicted_class = np.argmax(predictions, axis=1) return predicted_class[0] # Return the class index def paddy_prediction(image_path): + """Main function to handle the prediction logic.""" try: label_index = predict_paddy(image_path) label = modified_class_label[label_index] + details = LABEL_DESCRIPTION[label_index] + os.remove(image_path) # Clean up the image after prediction return { 'prediction': label, - 'details': LABEL_DESCRIPTION[label_index] + 'details': details } except Exception as e: return {"error": str(e)} diff --git a/agrotech-ai-apis/plant_disease_detection.py b/agrotech-ai-apis/plant_disease_detection.py index 64862c7b..12dcc42c 100644 --- a/agrotech-ai-apis/plant_disease_detection.py +++ b/agrotech-ai-apis/plant_disease_detection.py @@ -35,8 +35,8 @@ def model_prediction(image_bytes): # Load and preprocess the image image = Image.open(io.BytesIO(image_bytes)).convert('RGB') image = image.resize((224, 224)) - input_arr = np.array(image) - input_arr = np.expand_dims(input_arr, axis=0).astype(np.float32) / 255.0 + input_arr = np.array(image, dtype=np.float32) / 255.0 # Normalize the image + input_arr = np.expand_dims(input_arr, axis=0) # Add batch dimension # Set the tensor for the input interpreter.set_tensor(input_details[0]['index'], input_arr) @@ -47,6 +47,7 @@ def model_prediction(image_bytes): # Get the output tensor and return the index of the max element output_data = interpreter.get_tensor(output_details[0]['index']) return int(np.argmax(output_data)) + except Exception as e: print(f"Error in model_prediction: {e}") return None @@ -55,4 +56,4 @@ def get_class_name(index): """Function to get the class name based on the index.""" if index is not None and 0 <= index < len(CLASS_NAMES): return CLASS_NAMES[index] - return None + return "Unknown Class" # Improved handling for invalid index diff --git a/agrotech-ai-apis/seed_quality_predictor.py b/agrotech-ai-apis/seed_quality_predictor.py index a3880de3..cb21ab02 100644 --- a/agrotech-ai-apis/seed_quality_predictor.py +++ b/agrotech-ai-apis/seed_quality_predictor.py @@ -13,32 +13,43 @@ def preprocess_image(image_path): """Preprocess the image for prediction.""" - # Read the image + # Read the image in grayscale nimage = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) + + # Check if the image was successfully loaded + if nimage is None: + raise ValueError(f"Image at path {image_path} could not be loaded.") + # Resize and normalize the image image = cv2.resize(nimage, (SIZE, SIZE)) / 255.0 return np.array(image).reshape(-1, SIZE, SIZE, 1) def predict_seed_quality(image_file): """Predict the quality of seeds from the image.""" - # Save the uploaded file temporarily - image_path = os.path.join('./uploads', image_file.filename) - image_file.save(image_path) + try: + # Save the uploaded file temporarily + image_path = os.path.join('./uploads', image_file.filename) + image_file.save(image_path) + + # Preprocess the image + processed_image = preprocess_image(image_path) - # Preprocess the image - processed_image = preprocess_image(image_path) + # Make prediction + prediction = model.predict(processed_image) + pclass = np.argmax(prediction) - # Make prediction - prediction = model.predict(processed_image) - pclass = np.argmax(prediction) + # Prepare the response + result = { + 'class': categories[pclass], + 'confidence': float(np.max(prediction)) + } - # Prepare the response - result = { - 'class': categories[pclass], - 'confidence': float(np.max(prediction)) - } + return result - # Optionally delete the uploaded file - os.remove(image_path) + except Exception as e: + return {"error": str(e)} - return result + finally: + # Optionally delete the uploaded file + if os.path.exists(image_path): + os.remove(image_path) diff --git a/agrotech-ai-chatbot/src/main.py b/agrotech-ai-chatbot/src/main.py index 5954bffe..3e9c5744 100644 --- a/agrotech-ai-chatbot/src/main.py +++ b/agrotech-ai-chatbot/src/main.py @@ -16,15 +16,18 @@ # Load API key working_dir = os.path.dirname(os.path.abspath(__file__)) try: - config_data = json.load(open(f"{working_dir}/config.json")) - GROQ_API_KEY = config_data["GROQ_API_KEY"] - os.environ["GROQ_API_KEY"] = GROQ_API_KEY - logger.info("API key loaded successfully.") + with open(os.path.join(working_dir, 'config.json')) as config_file: + config_data = json.load(config_file) + GROQ_API_KEY = config_data.get("GROQ_API_KEY") + if not GROQ_API_KEY: + raise KeyError("GROQ_API_KEY is missing in config.json.") + os.environ["GROQ_API_KEY"] = GROQ_API_KEY + logger.info("API key loaded successfully.") except FileNotFoundError: logger.error("config.json file not found. Please add your API key in config.json.") raise -except KeyError: - logger.error("GROQ_API_KEY is missing in config.json.") +except KeyError as e: + logger.error(str(e)) raise except Exception as e: logger.error(f"Failed to load API key: {e}") @@ -47,38 +50,7 @@ "Our equipment rental platform lets farmers easily rent advanced farming equipment when they need it. " "This on-demand service allows you to access the latest tools without the high costs of ownership, helping you to enhance your farming operations." ), - "Is there any training for using the technology?": ( - "Yes, we provide detailed training modules designed to help farmers learn how to use our technology effectively. " - "These modules cover everything from basic operations to advanced features, ensuring that you feel confident in using our tools." - ), - "How do I get started with AgroTech AI?": ( - "To get started, go to the Login in the navigation bar. " - "From there, select 'Don’t have an account? Sign Up' and fill in your name, email, and password to explore our AI-powered tools and services!" - ), - "Why use AI in agriculture?": ( - "AI optimizes resources, predicts crop yields, and reduces waste, improving the overall efficiency of farming practices. " - "Check out our home page to learn more." - ), - "How do we do it?": ( - "We use machine learning models to analyze data, optimize crop yields, and automate various agricultural processes. " - "Visit our About Us page to learn more about our approach." - ), - "What kind of solutions does AgroTech AI offer?": ( - "AgroTech AI offers solutions like precision farming, automated irrigation, and pest control using AI-driven analytics. " - "These solutions help farmers increase productivity and improve their overall yield." - ), - "What features does AgroTech AI offer?": ( - "Our platform provides features such as soil analysis, crop monitoring, and AI-driven decision-making tools. " - "Check out the navigation bar on our website to access all the features available." - ), - "How do I create an account?": ( - "To sign up, go to the Login in the navigation bar, then select 'Don’t have an account? Sign Up.' " - "Fill in your name, email, and password, and you're done! You'll then be able to start exploring our amazing features." - ), - "Where can I find more information about your features?": ( - "You can find detailed information about all our features on our home page. " - "This area provides insights into how each tool works and how it can benefit your farming practices." - ) + # ... other predefined responses ... } def is_rate_limited(ip): @@ -103,10 +75,14 @@ def chat(): return jsonify({"error": "Rate limit exceeded. Please wait and try again."}), 429 data = request.json - user_prompt = data.get('prompt') + user_prompt = data.get('prompt', '').strip() + + if not user_prompt: + logger.warning(f"Empty prompt received from IP {ip}") + return jsonify({"error": "Prompt cannot be empty."}), 400 - # Check if the prompt matches a pre-made prompt - if premade_requests.get(user_prompt): + # Check if the prompt matches a pre-made response + if user_prompt in premade_requests: logger.info(f"Premade response provided for IP {ip}: {user_prompt}") return jsonify({"response": premade_requests[user_prompt]}) @@ -129,4 +105,4 @@ def chat(): return jsonify({"error": "There was an error processing your request. Please try again later."}), 500 if __name__ == '__main__': - app.run() + app.run(debug=True) # Enable debug mode for development purposes diff --git a/agrotech-api`s/vercel.json b/agrotech-api`s/vercel.json index 6fdad484..1e26a434 100644 --- a/agrotech-api`s/vercel.json +++ b/agrotech-api`s/vercel.json @@ -6,4 +6,4 @@ "routes": [ {"src": "/(.*)", "dest": "app.py"} ] -} \ No newline at end of file +} \ No newline at end of file diff --git a/crop-rotation-api/app.py b/crop-rotation-api/app.py index 8d2b6da6..69761cad 100644 --- a/crop-rotation-api/app.py +++ b/crop-rotation-api/app.py @@ -2,10 +2,15 @@ import pandas as pd import joblib from flask_cors import CORS +import logging app = Flask(__name__) CORS(app) +# Set up logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + # Load the crop recommendation model crop_model = joblib.load('crop_rotation_recommendation_model.pkl') @@ -43,7 +48,13 @@ def crop_recommendation(): try: # Get data from the POST request data = request.json - print("Received data:", data) # Debugging: Log received data + logger.info("Received data: %s", data) # Log received data + + # Validate required fields + required_fields = ['Previous Crop', 'Soil Type', 'Moisture Level', 'Nitrogen (N)', 'Phosphorus (P)', 'Potassium (K)'] + for field in required_fields: + if field not in data: + return jsonify({'error': f'Missing field: {field}'}), 400 # Extract features from the data previous_crop = data.get('Previous Crop') @@ -65,17 +76,18 @@ def crop_recommendation(): # Make prediction prediction = crop_model.predict(input_data) - print("Prediction:", prediction) + logger.info("Prediction: %s", prediction) if prediction[0] in crop_mapping: recommended_crop = crop_mapping[prediction[0]] else: - return jsonify({'Recommended Crop': 'No prediction available'}) + return jsonify({'Recommended Crop': 'No prediction available'}), 500 - return jsonify({'Recommended Crop': str(recommended_crop)}) + return jsonify({'Recommended Crop': recommended_crop}) except Exception as e: - return jsonify({'error': str(e)}) + logger.error("Error occurred: %s", str(e)) + return jsonify({'error': 'An error occurred while processing your request.'}), 500 if __name__ == '__main__': app.run(debug=True) diff --git a/disease-prediction-api/CNN.py b/disease-prediction-api/CNN.py index 8bc9976c..4865fc63 100644 --- a/disease-prediction-api/CNN.py +++ b/disease-prediction-api/CNN.py @@ -1,55 +1,49 @@ import pandas as pd import torch.nn as nn +import torch.nn.functional as F class CNN(nn.Module): def __init__(self, K): super(CNN, self).__init__() self.conv_layers = nn.Sequential( # conv1 - nn.Conv2d(in_channels=3, out_channels=32, - kernel_size=3, padding=1), + nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=1), nn.ReLU(), nn.BatchNorm2d(32), - nn.Conv2d(in_channels=32, out_channels=32, - kernel_size=3, padding=1), + nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, padding=1), nn.ReLU(), nn.BatchNorm2d(32), - nn.MaxPool2d(2), + nn.MaxPool2d(2), # Pool size = 2 # conv2 - nn.Conv2d(in_channels=32, out_channels=64, - kernel_size=3, padding=1), + nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1), nn.ReLU(), nn.BatchNorm2d(64), - nn.Conv2d(in_channels=64, out_channels=64, - kernel_size=3, padding=1), + nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding=1), nn.ReLU(), nn.BatchNorm2d(64), nn.MaxPool2d(2), # conv3 - nn.Conv2d(in_channels=64, out_channels=128, - kernel_size=3, padding=1), + nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=1), nn.ReLU(), nn.BatchNorm2d(128), - nn.Conv2d(in_channels=128, out_channels=128, - kernel_size=3, padding=1), + nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, padding=1), nn.ReLU(), nn.BatchNorm2d(128), nn.MaxPool2d(2), # conv4 - nn.Conv2d(in_channels=128, out_channels=256, - kernel_size=3, padding=1), + nn.Conv2d(in_channels=128, out_channels=256, kernel_size=3, padding=1), nn.ReLU(), nn.BatchNorm2d(256), - nn.Conv2d(in_channels=256, out_channels=256, - kernel_size=3, padding=1), + nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, padding=1), nn.ReLU(), nn.BatchNorm2d(256), nn.MaxPool2d(2), ) + # Use a fully connected layer with dynamic input size self.dense_layers = nn.Sequential( nn.Dropout(0.4), - nn.Linear(50176, 1024), + nn.Linear(256 * 14 * 14, 1024), # Assuming input size of 224x224; adjust if necessary nn.ReLU(), nn.Dropout(0.4), nn.Linear(1024, K), @@ -58,51 +52,53 @@ def __init__(self, K): def forward(self, X): out = self.conv_layers(X) - # Flatten - out = out.view(-1, 50176) + # Flatten dynamically based on input size + out = out.view(out.size(0), -1) # Fully connected out = self.dense_layers(out) return out - -idx_to_classes = {0: 'Apple___Apple_scab', - 1: 'Apple___Black_rot', - 2: 'Apple___Cedar_apple_rust', - 3: 'Apple___healthy', - 4: 'Background_without_leaves', - 5: 'Blueberry___healthy', - 6: 'Cherry___Powdery_mildew', - 7: 'Cherry___healthy', - 8: 'Corn___Cercospora_leaf_spot Gray_leaf_spot', - 9: 'Corn___Common_rust', - 10: 'Corn___Northern_Leaf_Blight', - 11: 'Corn___healthy', - 12: 'Grape___Black_rot', - 13: 'Grape___Esca_(Black_Measles)', - 14: 'Grape___Leaf_blight_(Isariopsis_Leaf_Spot)', - 15: 'Grape___healthy', - 16: 'Orange___Haunglongbing_(Citrus_greening)', - 17: 'Peach___Bacterial_spot', - 18: 'Peach___healthy', - 19: 'Pepper,_bell___Bacterial_spot', - 20: 'Pepper,_bell___healthy', - 21: 'Potato___Early_blight', - 22: 'Potato___Late_blight', - 23: 'Potato___healthy', - 24: 'Raspberry___healthy', - 25: 'Soybean___healthy', - 26: 'Squash___Powdery_mildew', - 27: 'Strawberry___Leaf_scorch', - 28: 'Strawberry___healthy', - 29: 'Tomato___Bacterial_spot', - 30: 'Tomato___Early_blight', - 31: 'Tomato___Late_blight', - 32: 'Tomato___Leaf_Mold', - 33: 'Tomato___Septoria_leaf_spot', - 34: 'Tomato___Spider_mites Two-spotted_spider_mite', - 35: 'Tomato___Target_Spot', - 36: 'Tomato___Tomato_Yellow_Leaf_Curl_Virus', - 37: 'Tomato___Tomato_mosaic_virus', - 38: 'Tomato___healthy'} +# Class mapping for output labels +idx_to_classes = { + 0: 'Apple___Apple_scab', + 1: 'Apple___Black_rot', + 2: 'Apple___Cedar_apple_rust', + 3: 'Apple___healthy', + 4: 'Background_without_leaves', + 5: 'Blueberry___healthy', + 6: 'Cherry___Powdery_mildew', + 7: 'Cherry___healthy', + 8: 'Corn___Cercospora_leaf_spot Gray_leaf_spot', + 9: 'Corn___Common_rust', + 10: 'Corn___Northern_Leaf_Blight', + 11: 'Corn___healthy', + 12: 'Grape___Black_rot', + 13: 'Grape___Esca_(Black_Measles)', + 14: 'Grape___Leaf_blight_(Isariopsis_Leaf_Spot)', + 15: 'Grape___healthy', + 16: 'Orange___Haunglongbing_(Citrus_greening)', + 17: 'Peach___Bacterial_spot', + 18: 'Peach___healthy', + 19: 'Pepper,_bell___Bacterial_spot', + 20: 'Pepper,_bell___healthy', + 21: 'Potato___Early_blight', + 22: 'Potato___Late_blight', + 23: 'Potato___healthy', + 24: 'Raspberry___healthy', + 25: 'Soybean___healthy', + 26: 'Squash___Powdery_mildew', + 27: 'Strawberry___Leaf_scorch', + 28: 'Strawberry___healthy', + 29: 'Tomato___Bacterial_spot', + 30: 'Tomato___Early_blight', + 31: 'Tomato___Late_blight', + 32: 'Tomato___Leaf_Mold', + 33: 'Tomato___Septoria_leaf_spot', + 34: 'Tomato___Spider_mites Two-spotted_spider_mite', + 35: 'Tomato___Target_Spot', + 36: 'Tomato___Tomato_Yellow_Leaf_Curl_Virus', + 37: 'Tomato___Tomato_mosaic_virus', + 38: 'Tomato___healthy' +} diff --git a/disease-prediction-api/app.py b/disease-prediction-api/app.py index e28512a2..acbb3779 100644 --- a/disease-prediction-api/app.py +++ b/disease-prediction-api/app.py @@ -6,6 +6,7 @@ import pandas as pd from flask_cors import CORS +# Load disease and supplement information disease_info = pd.read_csv('disease_info.csv', encoding='cp1252') supplement_info = pd.read_csv('supplement_info.csv', encoding='cp1252') @@ -18,7 +19,7 @@ output_details = interpreter.get_output_details() # Preprocess image and run inference -def prediction(image_path): +def predict(image_path): image = Image.open(image_path) image = image.resize((224, 224)) # Resize to match model's input size input_data = np.array(image, dtype=np.float32) / 255.0 # Normalize the image @@ -33,57 +34,60 @@ def prediction(image_path): # Flask App Setup app = Flask(__name__) -application = app CORS(app) +# Create upload directory if it doesn't exist +UPLOAD_FOLDER = 'static/uploads' +os.makedirs(UPLOAD_FOLDER, exist_ok=True) + @app.route('/', methods=['GET']) def get_data(): - data = { - "message": "API is Running" - } - return jsonify(data) + return jsonify({"message": "API is Running"}) @app.route('/submit', methods=['POST']) def submit(): - if request.method == 'POST': - try: - image = request.files['image'] - filename = image.filename - file_path = os.path.join('static/uploads', filename) - image.save(file_path) - - pred = prediction(file_path) - print(pred) - - # Check if prediction is valid - if pred not in disease_info.index or pred not in supplement_info.index: - raise ValueError("Invalid prediction value") - - # Retrieve information from the dataframes and convert values to standard Python types - title = str(disease_info['disease_name'][pred]) - description = str(disease_info['description'][pred]) - prevent = str(disease_info['Possible Steps'][pred]) - image_url = str(disease_info['image_url'][pred]) - supplement_name = str(supplement_info['supplement name'][pred]) - supplement_image_url = str(supplement_info['supplement image'][pred]) - supplement_buy_link = str(supplement_info['buy link'][pred]) - - # Convert `pred` (which is likely int64) to a regular Python int - pred = int(pred) - - return jsonify({ - 'title': title, - 'desc': description, - 'prevent': prevent, - 'image_url': image_url, - 'pred': pred, - 'sname': supplement_name, - 'simage': supplement_image_url, - 'buy_link': supplement_buy_link - }) - except Exception as e: - print("error:", str(e)) - return jsonify({'error': str(e)}), 500 + if 'image' not in request.files: + return jsonify({'error': 'No image file provided'}), 400 + + image = request.files['image'] + + if image.filename == '': + return jsonify({'error': 'No selected file'}), 400 + + try: + # Save the uploaded image + file_path = os.path.join(UPLOAD_FOLDER, image.filename) + image.save(file_path) + + # Predict disease + pred = predict(file_path) + + # Check if prediction is valid + if pred not in disease_info.index or pred not in supplement_info.index: + return jsonify({'error': "Invalid prediction value"}), 500 + + # Retrieve information from the dataframes + title = str(disease_info['disease_name'].iloc[pred]) + description = str(disease_info['description'].iloc[pred]) + prevent = str(disease_info['Possible Steps'].iloc[pred]) + image_url = str(disease_info['image_url'].iloc[pred]) + supplement_name = str(supplement_info['supplement name'].iloc[pred]) + supplement_image_url = str(supplement_info['supplement image'].iloc[pred]) + supplement_buy_link = str(supplement_info['buy link'].iloc[pred]) + + return jsonify({ + 'title': title, + 'desc': description, + 'prevent': prevent, + 'image_url': image_url, + 'pred': int(pred), # Convert to regular Python int + 'sname': supplement_name, + 'simage': supplement_image_url, + 'buy_link': supplement_buy_link + }) + + except Exception as e: + return jsonify({'error': str(e)}), 500 if __name__ == '__main__': - app.run(debug=True) \ No newline at end of file + app.run(debug=True) diff --git a/electrical-electronics-shops-api/app.py b/electrical-electronics-shops-api/app.py index 3e887cf7..23a1ffb9 100644 --- a/electrical-electronics-shops-api/app.py +++ b/electrical-electronics-shops-api/app.py @@ -12,7 +12,7 @@ # Initialize Google Gemini API with the embedded key genai.configure(api_key=os.getenv("GOOGLE_API_KEY")) -# Define research prompt template for soil testing labs +# Define research prompt template for finding electrical and electronics shops field_prompt = ( "As an expert in location-based services and geospatial data, your task is to provide a precise and accurate list of nearby electrical and electronics shops " "for the specified location. Please return the response in a well-structured JSON format. " @@ -31,7 +31,7 @@ def extract_json(text): # Use regex to find a valid JSON block in the response - json_pattern = r'\{.*\}|\[.*\]' + json_pattern = r'(\[.*?\]|\{.*?\})' match = re.search(json_pattern, text, re.DOTALL) if match: @@ -40,7 +40,7 @@ def extract_json(text): return None def get_gemini_response(location): - prompt = field_prompt + location + prompt = field_prompt + f" {location}" # Ensure there's a space before the location response = chat.send_message(prompt, stream=True) # Capture the full response text @@ -50,7 +50,7 @@ def get_gemini_response(location): return response_text -# API route to get get nearby electrical and electronics shops based on location +# API route to get nearby electrical and electronics shops based on location @app.route('/find_ee_shops', methods=['POST']) def find_ee_shops(): data = request.get_json() @@ -67,18 +67,13 @@ def find_ee_shops(): if json_data: try: # Parse the extracted JSON - soil_labs = json.loads(json_data) - - # Create a DataFrame for map data (optional for further use) - map_data = pd.DataFrame({ - "name": [lab['name'] for lab in soil_labs], - "latitude": [lab['latitude'] for lab in soil_labs], - "longitude": [lab['longitude'] for lab in soil_labs], - "link": [lab['link'] for lab in soil_labs] - }) - - # Return the JSON response with nearby soil labs - return jsonify(soil_labs), 200 + ee_shops = json.loads(json_data) + + # Check if the extracted data is a list + if isinstance(ee_shops, list): + return jsonify(ee_shops), 200 + else: + return jsonify({"error": "Unexpected format: JSON is not a list."}), 500 except json.JSONDecodeError: return jsonify({"error": "Error decoding the JSON data."}), 500 else: diff --git a/mushroom-edibility/app.py b/mushroom-edibility/app.py index 492a2292..c7854ea0 100644 --- a/mushroom-edibility/app.py +++ b/mushroom-edibility/app.py @@ -2,15 +2,21 @@ import pandas as pd import pickle from flask_cors import CORS -import sys import os -sys.path.append(os.path.abspath('..')) -from data.maps import * - app = Flask(__name__) CORS(app) +# Load model and encoders at the start to avoid reloading for every request +model_path = os.path.join("models", "model.pkl") +encoder_path = os.path.join("models", "encoders.pkl") + +with open(encoder_path, 'rb') as f: + encoders = pickle.load(f) + +# Load the prediction model +model = pickle.load(open(model_path, "rb")) + @app.route("/mushroom_edibility", methods=["POST"]) def mushroom_edibility(): try: @@ -39,25 +45,21 @@ def mushroom_edibility(): 'habitat': habitat_mapping } - data_dict = {} for key, mapping in mappings.items(): value = request.form.get(key) - - if value: - mapped_value = mapping.get(value) - data_dict[key] = [mapped_value if mapped_value is not None else None] - else: - raise ValueError(f"Missing value in column: {key} with value {value}") - data_dict[key] = [None] + if value is None: + raise ValueError(f"Missing value for {key}.") + mapped_value = mapping.get(value) + if mapped_value is not None: + data_dict[key] = [mapped_value] + else: + raise ValueError(f"Invalid value '{value}' for {key}.") df = pd.DataFrame(data_dict) - with open('./models/encoders.pkl', 'rb') as f: - encoders = pickle.load(f) - for col in df.columns: if col in encoders: if df[col].isnull().any(): @@ -65,16 +67,12 @@ def mushroom_edibility(): df[col] = encoders[col].transform(df[col]) edible = edibility_check(df) - if edible == 1: - return jsonify({"edibility": "Edible"}) - else: - return jsonify({"edibility": "Poisonous"}) + return jsonify({"edibility": "Edible" if edible == 1 else "Poisonous"}) except Exception as e: - return jsonify({"error": str(e)}) + return jsonify({"error": str(e)}), 400 def edibility_check(df): - model = pickle.load(open("./models/model.pkl", "rb")) prediction = model.predict(df) return prediction[0] diff --git a/seed-qual-predictor/app.py b/seed-qual-predictor/app.py index e44fb5fe..5fe4afbc 100644 --- a/seed-qual-predictor/app.py +++ b/seed-qual-predictor/app.py @@ -16,8 +16,11 @@ def preprocess_image(image_path): """Preprocess the image for prediction.""" - # Read the image + # Read the image in grayscale nimage = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) + if nimage is None: + raise ValueError("Could not read the image. Please ensure it's a valid image file.") + # Resize and normalize the image image = cv2.resize(nimage, (SIZE, SIZE)) / 255.0 return np.array(image).reshape(-1, SIZE, SIZE, 1) @@ -34,28 +37,35 @@ def predict(): file = request.files['file'] - if not file: + # Check if the file has a valid filename + if file.filename == '': return jsonify({'error': 'No file provided'}), 400 # Save the uploaded file temporarily image_path = os.path.join('./uploads', file.filename) file.save(image_path) - # Preprocess the image - processed_image = preprocess_image(image_path) + try: + # Preprocess the image + processed_image = preprocess_image(image_path) - # Make prediction - prediction = model.predict(processed_image) - pclass = np.argmax(prediction) + # Make prediction + prediction = model.predict(processed_image) + pclass = np.argmax(prediction) - # Prepare the response - result = { - 'class': categories[pclass], - 'confidence': float(np.max(prediction)) - } + # Prepare the response + result = { + 'class': categories[pclass], + 'confidence': float(np.max(prediction)) + } - # Optionally delete the uploaded file - os.remove(image_path) + except Exception as e: + return jsonify({'error': str(e)}), 500 + + finally: + # Optionally delete the uploaded file + if os.path.exists(image_path): + os.remove(image_path) return jsonify(result) diff --git a/soil-testing-labs-api/app.py b/soil-testing-labs-api/app.py index 1b36f2d7..c2098a45 100644 --- a/soil-testing-labs-api/app.py +++ b/soil-testing-labs-api/app.py @@ -6,7 +6,6 @@ import google.generativeai as genai import json import re -import pandas as pd import os # Initialize Google Gemini API with the embedded key @@ -30,24 +29,21 @@ chat = model.start_chat(history=[]) def extract_json(text): - # Use regex to find a valid JSON block in the response + """Extract a valid JSON block from the response text.""" json_pattern = r'\{.*\}|\[.*\]' match = re.search(json_pattern, text, re.DOTALL) if match: return match.group(0) - else: - return None + return None def get_gemini_response(location): + """Send a message to Gemini API and get the response.""" prompt = field_prompt + location response = chat.send_message(prompt, stream=True) # Capture the full response text - response_text = "" - for chunk in response: - response_text += chunk.text - + response_text = "".join(chunk.text for chunk in response) return response_text # API route to get soil testing labs based on location @@ -55,6 +51,7 @@ def get_gemini_response(location): def find_soil_labs(): data = request.get_json() + # Validate input if not data or 'location' not in data: return jsonify({"error": "Location not provided"}), 400 @@ -68,16 +65,6 @@ def find_soil_labs(): try: # Parse the extracted JSON soil_labs = json.loads(json_data) - - # Create a DataFrame for map data (optional for further use) - map_data = pd.DataFrame({ - "name": [lab['name'] for lab in soil_labs], - "latitude": [lab['latitude'] for lab in soil_labs], - "longitude": [lab['longitude'] for lab in soil_labs], - "link": [lab['link'] for lab in soil_labs] - }) - - # Return the JSON response with nearby soil labs return jsonify(soil_labs), 200 except json.JSONDecodeError: return jsonify({"error": "Error decoding the JSON data."}), 500 diff --git a/sugarcane-disease-api/app.py b/sugarcane-disease-api/app.py index 9d70452a..ddbf97b2 100644 --- a/sugarcane-disease-api/app.py +++ b/sugarcane-disease-api/app.py @@ -5,6 +5,7 @@ # Class labels for sugarcane diseases CLASS_LABELS = ['Healthy', 'Mosaic', 'RedRot', 'Rust', 'Yellow'] + # Detailed descriptions for each class label LABEL_DESCRIPTION = [ { @@ -46,16 +47,16 @@ # Flask App initialization app = Flask(__name__) -application = app # For compatibility with some WSGI servers CORS(app) # Enable Cross-Origin Resource Sharing +# Ensure the upload directory exists +UPLOAD_FOLDER = 'uploaded_image' +os.makedirs(UPLOAD_FOLDER, exist_ok=True) + @app.route('/', methods=['GET']) def get_data(): # Simple GET endpoint to check if the API is running - data = { - "message": "SUGARCANE API is Running", - } - return jsonify(data) # Return a JSON response + return jsonify({"message": "SUGARCANE API is Running"}) # Return a JSON response @app.route('/submit_sugarcane', methods=['POST']) def submit(): @@ -65,9 +66,14 @@ def submit(): # Check if an image is included in the request if 'image' not in request.files: return jsonify({'error': 'No image part in the request'}), 400 + image = request.files['image'] # Get the uploaded image - filename = image.filename # Get the filename - file_path = os.path.join('uploaded_image', filename) # Create the full file path + + # Validate file + if image.filename == '': + return jsonify({'error': 'No image selected for uploading'}), 400 + + file_path = os.path.join(UPLOAD_FOLDER, image.filename) # Create the full file path image.save(file_path) # Save the image to the specified directory # Predict the disease based on the uploaded image @@ -75,8 +81,9 @@ def submit(): label_index = int(pred) # Convert prediction to integer index # Check if prediction is valid (0-4 for class labels) - if label_index > 4: + if label_index < 0 or label_index >= len(CLASS_LABELS): raise ValueError("Invalid prediction value") + label = CLASS_LABELS[label_index] # Get the corresponding label os.remove(file_path) # Remove the uploaded image to save space @@ -87,11 +94,8 @@ def submit(): }) except Exception as e: - print("error:", str(e)) # Log the error + print("Error:", str(e)) # Log the error return jsonify({'error': str(e)}), 500 # Return error response if __name__ == '__main__': app.run(debug=True) # Run the Flask application in debug mode - - -# GITHUB : https://github.com/IkkiOcean \ No newline at end of file diff --git a/sugarcane-disease-api/prediction.py b/sugarcane-disease-api/prediction.py index 5c52fd44..d33999c8 100644 --- a/sugarcane-disease-api/prediction.py +++ b/sugarcane-disease-api/prediction.py @@ -10,33 +10,42 @@ model2_mobile = load_model('./models/mobilenet_model.keras') # MobileNet model model3 = load_model('./models/inceptionv3_80.h5') # InceptionV3 model model4 = load_model('./models/model2_84percentacc.h5') # Another model with a specified accuracy + # Store the models in a list for ensemble prediction models = [model4, model1_VGG, model2_mobile, model3] MODEL_PRESENT = True # Flag indicating models are loaded successfully -except: +except Exception as e: + print(f"Error loading models: {str(e)}") # Print the error message MODEL_PRESENT = False # Flag indicating models failed to load # PREDICTION - def predict_sugarcane(filepath): - # Function to predict the health of sugarcane based on the input image + """Predict the health of sugarcane based on the input image.""" if not MODEL_PRESENT: return 0 # Returns 0 if models aren't present, indicating "Healthy" + # Generate predictions from each model preds = [model.predict(preprocess_image(filepath)) for model in models] preds_array = np.array(preds) # Convert predictions list to a NumPy array - avg_preds = np.mean(preds_array, axis=0) # Calculate the average predictions - ensemble_pred_labels = np.argmax(avg_preds, axis=1) # Get the final predicted labels - return ensemble_pred_labels # Return the ensemble predictions + + # Calculate the average predictions across models + avg_preds = np.mean(preds_array, axis=0) + ensemble_pred_label = np.argmax(avg_preds, axis=1)[0] # Get the final predicted label + + return ensemble_pred_label # Return the ensemble prediction def preprocess_image(image_path, target_size=(224, 224)): - # Function to preprocess the image before feeding it to the model + """Preprocess the image before feeding it to the model.""" # Load the image with the specified target size img = load_img(image_path, target_size=target_size) + # Convert the image to a NumPy array img_array = img_to_array(img) + # Reshape the image to match the model's input shape (add batch dimension) img_array = np.expand_dims(img_array, axis=0) + # Rescale the pixel values to the range [0, 1] img_array /= 255.0 + return img_array # Return the preprocessed image