├── LICENSE ├── README.md ├── README.tr.md ├── keyforge3d.png ├── keyforge3d.py └── sample.png /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Mehmet T. AKALIN 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KeyForge3D 2 | 3 | ![KeyForge3D Logo](keyforge3d.png) 4 | 5 | **KeyForge3D** is an innovative application that extracts the shape of a physical key from a photo, generates a 3D model of the key, and exports it as an STL file for 3D printing. This tool is designed for locksmiths, hobbyists, or anyone needing a quick way to replicate a key using a 3D printer. The app features a user-friendly GUI built with Tkinter, making it easy to upload an image, process the key, and generate a 3D model. 6 | 7 | ## Features 8 | 9 | - **Key Shape Extraction**: Upload a photo of a key to extract its 2D profile. 10 | - **Bitting Analysis**: Automatically detect and analyze the key's bitting pattern (e.g., "05624"). 11 | - **3D Model Generation**: Convert the 2D key profile into a 3D model with accurate cuts and dimensions. 12 | - **STL Export**: Export the 3D model as an STL file, ready for 3D printing. 13 | - **User-Friendly GUI**: Simple interface to upload images and generate models with a single click. 14 | - **Scalability**: Scale the key to real-world dimensions (default: 1 pixel = 0.1 mm; can be adjusted with a reference object). 15 | 16 | ## Demo 17 | 18 | ![KeyForge3D Sample](sample.png) 19 | 20 | The app processes a photo of a key, extracts its shape, and generates a 3D model like the one shown above. The bitting code (e.g., "05624") is also displayed for reference. 21 | 22 | ## Installation 23 | 24 | ### Prerequisites 25 | 26 | - **Python 3.8+**: Ensure Python is installed on your system. 27 | - **pip**: Python package manager for installing dependencies. 28 | - **3D Printer (Optional)**: To print the generated key models. 29 | 30 | ### Dependencies 31 | 32 | KeyForge3D relies on the following Python libraries: 33 | 34 | - `opencv-python`: For image processing and key shape extraction. 35 | - `numpy`: For numerical operations. 36 | - `trimesh`: For 3D model generation and STL export. 37 | - `shapely`: For polygon operations. 38 | - `pillow`: For image display in the GUI. 39 | 40 | Install the dependencies using the following command: 41 | 42 | ```bash 43 | pip install opencv-python numpy trimesh shapely pillow 44 | ``` 45 | 46 | ### Clone the Repository 47 | 48 | Clone the KeyForge3D repository to your local machine: 49 | 50 | ```bash 51 | git clone https://github.com/makalin/KeyForge3D.git 52 | cd KeyForge3D 53 | ``` 54 | 55 | ## Usage 56 | 57 | 1. **Run the App**: 58 | - Run the main script to launch the GUI: 59 | 60 | ```bash 61 | python keyforge3d.py 62 | ``` 63 | 64 | 2. **Upload a Key Photo**: 65 | - Click the "Upload Key Image" button and select a photo of a key. 66 | - The key should be placed on a plain background (e.g., white paper) with good lighting for best results. 67 | - Optionally, include a reference object (e.g., a coin) for accurate scaling (scaling is currently set to 1 pixel = 0.1 mm). 68 | 69 | 3. **Process the Key**: 70 | - Click the "Process Key and Generate 3D Model" button. 71 | - The app will process the image, display the bitting code, and save the 3D model as `key_model.stl`. 72 | 73 | 4. **3D Printing**: 74 | - Open the `key_model.stl` file in your 3D printing software (e.g., Cura, PrusaSlicer). 75 | - Print the key using a strong material like PLA or ABS. Use a high resolution (e.g., 0.1 mm layer height) for accurate bitting cuts. 76 | 77 | ## Code Overview 78 | 79 | The main script (`keyforge3d.py`) includes: 80 | 81 | - **GUI**: Built with Tkinter for user interaction. 82 | - **Image Processing**: Uses OpenCV to detect the key's outline and analyze its bitting pattern. 83 | - **3D Model Generation**: Uses Trimesh to create a 3D model and export it as an STL file. 84 | - **Error Handling**: Includes basic error handling for invalid images or processing failures. 85 | 86 | ## Roadmap 87 | 88 | - [ ] Add a 3D model preview within the app. 89 | - [ ] Support for scaling using a reference object (e.g., a coin). 90 | - [ ] Add key type identification (e.g., Schlage SC4, Kwikset KW1). 91 | - [ ] Improve bitting analysis accuracy with machine learning. 92 | - [ ] Create a mobile app version with camera integration. 93 | - [ ] Add support for more key profiles and bitting standards. 94 | 95 | ## Contributing 96 | 97 | Contributions are welcome! To contribute: 98 | 99 | 1. Fork the repository. 100 | 2. Create a new branch (`git checkout -b feature/your-feature`). 101 | 3. Make your changes and commit them (`git commit -m "Add your feature"`). 102 | 4. Push to your branch (`git push origin feature/your-feature`). 103 | 5. Open a pull request. 104 | 105 | Please ensure your code follows the project's coding style and includes appropriate tests. 106 | 107 | ## License 108 | 109 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. 110 | 111 | ## Acknowledgments 112 | 113 | - Inspired by locksmith tools for key bitting analysis. 114 | - Built with the help of open-source libraries like OpenCV, Trimesh, and Tkinter. 115 | 116 | ## Contact 117 | 118 | For questions, suggestions, or feedback, feel free to open an issue or reach out. 119 | -------------------------------------------------------------------------------- /README.tr.md: -------------------------------------------------------------------------------- 1 | # KeyForge3D 2 | 3 | ![KeyForge3D Logosu](keyforge3d.png) 4 | 5 | **KeyForge3D**, fiziksel bir anahtarın fotoğrafından şeklini çıkaran, anahtarın 3D modelini oluşturan ve bunu 3D yazdırma için STL dosyası olarak dışa aktaran yenilikçi bir uygulamadır. Bu araç, çilingirler, hobi meraklıları veya bir anahtarı 3D yazıcıyla hızlıca çoğaltması gereken herkes için tasarlanmıştır. Uygulama, Tkinter ile oluşturulmuş kullanıcı dostu bir arayüz sunar; böylece bir görüntü yüklemek, anahtarı işlemek ve 3D model üretmek oldukça kolaydır. 6 | 7 | ## Özellikler 8 | 9 | - **Anahtar Şekli Çıkartma**: Bir anahtarın 2D profilini çıkarmak için bir fotoğraf yükleyin. 10 | - **Bitting Analizi**: Anahtarın diş (bitting) desenini otomatik olarak tespit ve analiz eder (örneğin, "05624"). 11 | - **3D Model Oluşturma**: 2D profil, doğru kesimler ve boyutlarla 3D modele dönüştürülür. 12 | - **STL Dışa Aktarımı**: 3D model, STL dosyası olarak dışa aktarılır ve yazdırılmaya hazırdır. 13 | - **Kullanıcı Dostu Arayüz**: Tek tıklamayla görsel yükleyip model üretmek için basit bir GUI. 14 | - **Ölçekleme Desteği**: Anahtar gerçeğe uygun ölçekte oluşturulur (varsayılan: 1 piksel = 0.1 mm; referans nesnesiyle ayarlanabilir). 15 | 16 | ## Demo 17 | 18 | ![KeyForge3D Örneği](sample.png) 19 | 20 | Uygulama bir anahtarın fotoğrafını işler, şeklini çıkartır ve yukarıda gösterildiği gibi bir 3D model üretir. Ayrıca bitting kodunu (örnek: "05624") da gösterir. 21 | 22 | ## Kurulum 23 | 24 | ### Gereksinimler 25 | 26 | - **Python 3.8+** 27 | - **pip** – Bağımlılıkları yüklemek için 28 | - **3D Yazıcı (İsteğe Bağlı)** – Üretilen anahtarları fiziksel olarak yazdırmak için 29 | 30 | ### Bağımlılıklar 31 | 32 | Gerekli Python kütüphaneleri: 33 | 34 | - `opencv-python` – Görüntü işleme ve şekil çıkarma 35 | - `numpy` – Sayısal işlemler 36 | - `trimesh` – 3D model üretimi ve STL dışa aktarımı 37 | - `shapely` – Çokgen işlemleri 38 | - `pillow` – GUI içinde görüntü gösterimi 39 | 40 | Kurulum komutu: 41 | 42 | ```bash 43 | pip install opencv-python numpy trimesh shapely pillow 44 | ``` 45 | 46 | ### Depoyu Klonlayın 47 | 48 | ```bash 49 | git clone https://github.com/makalin/KeyForge3D.git 50 | cd KeyForge3D 51 | ``` 52 | 53 | ## Kullanım 54 | 55 | 1. **Uygulamayı Başlatın**: 56 | 57 | ```bash 58 | python keyforge3d.py 59 | ``` 60 | 61 | 2. **Bir Anahtar Fotoğrafı Yükleyin**: 62 | 63 | - "Anahtar Görseli Yükle" düğmesine tıklayın ve bir anahtar fotoğrafı seçin. 64 | - En iyi sonuçlar için düz bir arka planda (örneğin beyaz kağıt) ve iyi aydınlatılmış bir görüntü kullanın. 65 | - İsteğe bağlı olarak, ölçekleme için referans nesnesi (örneğin bir madeni para) ekleyebilirsiniz. (Varsayılan: 1 piksel = 0.1 mm) 66 | 67 | 3. **Anahtarı İşleyin**: 68 | 69 | - "Anahtarı İşle ve 3D Model Üret" düğmesine tıklayın. 70 | - Uygulama görüntüyü işler, bitting kodunu gösterir ve modeli `key_model.stl` olarak kaydeder. 71 | 72 | 4. **3D Yazdırma**: 73 | 74 | - STL dosyasını Cura veya PrusaSlicer gibi bir yazıcı yazılımında açın. 75 | - PLA veya ABS gibi dayanıklı bir filament kullanın. 76 | - Kesimlerin doğruluğu için yüksek çözünürlük (örneğin 0.1 mm katman yüksekliği) önerilir. 77 | 78 | ## Kod Genel Bakışı 79 | 80 | Ana betik (`keyforge3d.py`) şunları içerir: 81 | 82 | - **GUI** – Tkinter ile yapılmıştır. 83 | - **Görüntü İşleme** – OpenCV ile kontur ve bitting tespiti yapılır. 84 | - **3D Modelleme** – Trimesh ile STL dosyası oluşturulur. 85 | - **Hata Yönetimi** – Geçersiz görüntü veya işlem hataları için temel hata kontrolü içerir. 86 | 87 | ## Yol Haritası 88 | 89 | - [ ] Uygulamada 3D model önizlemesi 90 | - [ ] Referans nesnesiyle ölçeklendirme desteği 91 | - [ ] Anahtar tipi tanıma (örn: Schlage SC4, Kwikset KW1) 92 | - [ ] Makine öğrenimi ile bitting doğruluğunu artırma 93 | - [ ] Kameralı mobil uygulama sürümü 94 | - [ ] Daha fazla anahtar profili ve bitting standardı desteği 95 | 96 | ## Katkıda Bulunma 97 | 98 | Katkılarınız gerçekten önemli. Her türlü öneri ve yorumunuzu iletin. 99 | Katkıda bulunmak için: 100 | 101 | 1. Repoyu çatallayın 102 | 2. Yeni bir dal oluşturun: 103 | ```bash 104 | git checkout -b ozellik/senin-ozelligin 105 | ``` 106 | 3. Değişiklikleri yapın ve commit’leyin: 107 | ```bash 108 | git commit -m "Özellik eklendi" 109 | ``` 110 | 4. Dalı gönderin: 111 | ```bash 112 | git push origin ozellik/senin-ozelligin 113 | ``` 114 | 5. Pull Request açın ✅ 115 | 116 | Lütfen kod stiline ve test kapsamına dikkat edin. 117 | 118 | ## Lisans 119 | 120 | Bu proje [MIT Lisansı](LICENSE) ile lisanslanmıştır. 121 | 122 | ## Teşekkürler 123 | 124 | - Anahtar bitting analizine ilham olan çilingir araçlarına 125 | - OpenCV, Trimesh ve Tkinter gibi açık kaynak kütüphanelere 126 | 127 | ## İletişim 128 | 129 | Sorular, öneriler veya geri bildirimler için lütfen bir "issue" açın veya iletişime geçin. 130 | -------------------------------------------------------------------------------- /keyforge3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/makalin/KeyForge3D/0916b28e598e06012f035ad506bfaeca79c31564/keyforge3d.png -------------------------------------------------------------------------------- /keyforge3d.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import trimesh 4 | from shapely.geometry import Polygon 5 | import tkinter as tk 6 | from tkinter import filedialog, messagebox 7 | from PIL import Image, ImageTk 8 | import os 9 | 10 | class KeyForge3DApp: 11 | def __init__(self, root): 12 | self.root = root 13 | self.root.title("KeyForge3D - Key Shape Extractor and 3D Model Generator") 14 | self.root.geometry("600x400") 15 | 16 | # Variables 17 | self.image_path = None 18 | self.scale_factor = 0.1 # Default scale: 1 pixel = 0.1 mm (adjust with a reference object if needed) 19 | self.key_thickness = 2.0 # Thickness of the key in mm 20 | self.num_cuts = 5 # Number of bitting cuts (adjust based on key type) 21 | self.cut_depth_increment = 0.33 # Depth increment per bitting value in mm (e.g., Schlage standard) 22 | 23 | # GUI Elements 24 | self.label = tk.Label(root, text="KeyForge3D: Extract and 3D Print Keys", font=("Arial", 16)) 25 | self.label.pack(pady=10) 26 | 27 | self.upload_button = tk.Button(root, text="Upload Key Image", command=self.upload_image) 28 | self.upload_button.pack(pady=5) 29 | 30 | self.image_label = tk.Label(root) 31 | self.image_label.pack(pady=5) 32 | 33 | self.process_button = tk.Button(root, text="Process Key and Generate 3D Model", command=self.process_key, state=tk.DISABLED) 34 | self.process_button.pack(pady=5) 35 | 36 | self.result_label = tk.Label(root, text="", font=("Arial", 12)) 37 | self.result_label.pack(pady=5) 38 | 39 | def upload_image(self): 40 | """Allow the user to upload an image of a key.""" 41 | self.image_path = filedialog.askopenfilename(filetypes=[("Image Files", "*.jpg *.jpeg *.png")]) 42 | if self.image_path: 43 | # Display the uploaded image 44 | img = Image.open(self.image_path) 45 | img = img.resize((300, 150), Image.Resampling.LANCZOS) # Resize for display 46 | img_tk = ImageTk.PhotoImage(img) 47 | self.image_label.config(image=img_tk) 48 | self.image_label.image = img_tk # Keep a reference to avoid garbage collection 49 | self.process_button.config(state=tk.NORMAL) 50 | self.result_label.config(text="Image uploaded. Click 'Process Key' to generate the 3D model.") 51 | 52 | def process_key(self): 53 | """Process the key image, extract the shape, and generate a 3D model.""" 54 | if not self.image_path: 55 | messagebox.showerror("Error", "Please upload an image first.") 56 | return 57 | 58 | try: 59 | # Load the image 60 | image = cv2.imread(self.image_path) 61 | if image is None: 62 | raise ValueError("Could not load the image.") 63 | 64 | gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 65 | 66 | # Apply Gaussian blur and edge detection 67 | blurred = cv2.GaussianBlur(gray, (5, 5), 0) 68 | edges = cv2.Canny(blurred, 50, 150) 69 | 70 | # Find contours 71 | contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 72 | 73 | # Filter contours to find the key (long, thin shape) 74 | key_contour = None 75 | for contour in contours: 76 | perimeter = cv2.arcLength(contour, True) 77 | approx = cv2.approxPolyDP(contour, 0.02 * perimeter, True) 78 | x, y, w, h = cv2.boundingRect(contour) 79 | aspect_ratio = w / float(h) 80 | if 2 < aspect_ratio < 5 and w > 100: # Adjust these values based on your image 81 | key_contour = contour 82 | break 83 | 84 | if key_contour is None: 85 | raise ValueError("Could not detect a key in the image.") 86 | 87 | # Extract the key region 88 | x, y, w, h = cv2.boundingRect(key_contour) 89 | key_region = gray[y:y+h, x:x+w] 90 | 91 | # Convert contour to a 2D polygon 92 | points = key_contour.reshape(-1, 2) * self.scale_factor 93 | key_polygon = Polygon(points) 94 | 95 | # Extrude the polygon to create a 3D model 96 | key_mesh = trimesh.creation.extrude_polygon(key_polygon, height=self.key_thickness) 97 | 98 | # Analyze the bitting 99 | blade = key_region[h//2:h, :] # Focus on the lower half (blade) 100 | height, width = blade.shape 101 | segment_width = width // self.num_cuts 102 | bitting = [] 103 | 104 | for i in range(self.num_cuts): 105 | segment = blade[:, i * segment_width:(i + 1) * segment_width] 106 | # Find the highest point (shallowest cut) in the segment 107 | cut_depth = np.argmax(segment, axis=0).mean() 108 | # Scale the depth to real-world dimensions 109 | depth_value = (cut_depth / height) * self.cut_depth_increment * 9 110 | bitting.append(depth_value) 111 | 112 | # Apply bitting cuts to the 3D model 113 | for i, depth in enumerate(bitting): 114 | cut_x = (i * segment_width * self.scale_factor) + (segment_width * self.scale_factor / 2) 115 | cut_y = 0 # Adjust based on blade position 116 | cut_width = segment_width * self.scale_factor 117 | cut_height = depth 118 | # Create a box for the cut and subtract it from the key mesh 119 | cut_box = trimesh.creation.box( 120 | extents=[cut_width, cut_height, self.key_thickness + 1], 121 | transform=trimesh.transformations.translation_matrix([cut_x, cut_y, 0]) 122 | ) 123 | key_mesh = key_mesh.difference(cut_box) 124 | 125 | # Export the 3D model as STL 126 | output_path = "key_model.stl" 127 | key_mesh.export(output_path) 128 | 129 | # Display the results 130 | bitting_code = [int(d / self.cut_depth_increment) for d in bitting] 131 | self.result_label.config( 132 | text=f"Success! Bitting Code: {bitting_code}\n3D Model saved as '{output_path}'" 133 | ) 134 | messagebox.showinfo("Success", f"3D model generated and saved as '{output_path}'.") 135 | 136 | except Exception as e: 137 | messagebox.showerror("Error", f"Failed to process the key: {str(e)}") 138 | self.result_label.config(text="Error processing the key. See error message.") 139 | 140 | if __name__ == "__main__": 141 | root = tk.Tk() 142 | app = KeyForge3DApp(root) 143 | root.mainloop() -------------------------------------------------------------------------------- /sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/makalin/KeyForge3D/0916b28e598e06012f035ad506bfaeca79c31564/sample.png --------------------------------------------------------------------------------