In this tutorial, we will explore the powerful capabilities of DelphiFMX and delve into the fascinating realm of K-means clustering visualization. Imagine easily analyzing and visualizing data patterns, empowering users to gain valuable insights and make data-driven decisions. Join us on this exciting journey as we build a K-means clustering visualization app using DelphiFMX, leveraging its robust features and seamless integration with the K-means algorithm.
Table of Contents
What is Unsupervised Learning and When is it Useful?
Unsupervised learning is a type of machine learning where the model learns patterns and structures from unlabeled data without any predefined target variable. In unsupervised learning, the goal is to discover the underlying structure or relationships within the data. Unlike supervised learning, where the model is trained on labeled data with known outputs, unsupervised learning algorithms work on unannotated data. These algorithms aim to find hidden patterns, clusters, or associations within the data.
For instance, unsupervised learning algorithms can help understand the data by identifying patterns, outliers, and relationships between variables. This exploratory analysis can provide insights into the dataset before further analysis or modeling.
Clustering algorithms, such as K-means, DBSCAN, or hierarchical clustering, group similar data points together based on their features or distances. It is valuable for customer segmentation, market research, image segmentation, and anomaly detection. More applications include dimensionality reduction, feature extraction, and anomaly detection.
Which Tools Can Be Used For Creating GUIs for AI-Related Apps?
We will leverage DelphiFMX’s powerful components and functionality to create our K-means clustering visualization app. We will design an intuitive user interface that allows users to interact with the app and input their data. The app will then perform the K-means clustering algorithm on the provided data and visualize the resulting clusters using dynamic charts and visual elements.
Creating visualization apps can be thrilling and rewarding, especially with the right tools. Delphi FMX offers a rich ecosystem that simplifies and accelerates the development process, making it an excellent choice for creating a K-means clustering visualization app. By combining the power of Delphi FMX’s GUI development tools (such as Delphi IDE and Delphi4PythonExporter) and its seamless integration capabilities, we can unlock the full potential of the K-means algorithm and provide users with an intuitive and interactive visualization experience.
How to Create a K-Means Clustering Desktop App With a Stunning GUI?
What Libraries and Software Do You Need for this Tutorial?
To implement the code that utilizes the Python libraries Pillow, NumPy, OpenCV (cv2), and scikit-learn (sklearn), you need to set up some prerequisites. Firstly, ensure that you have installed Delphi Software. These tools will enable you to create the K-means app with a visually appealing user interface. Additionally, make sure to have the Delphi4PythonExporter tool installed, as it facilitates seamless integration between Delphi and Python.
You will need a text editor or integrated development environment (IDE) that supports Python programming. We recommend using PyScripter, which provides a convenient environment for editing and executing Python code within Delphi. If you don’t have these tools installed, we recommend checking out the article “Powerful Python GUI Project Setup” to help you get started.
Lastly, to run the code successfully, install the necessary Python libraries. Execute the following commands in the command prompt or terminal:
1 2 3 4 5 |
pip install pillow pip install opencv-python pip install numpy pip install scikit-learn |
You can access the complete code for this tutorial from our GitHub repository. Simply visit the following link to obtain the code and related resources:
https://github.com/Embarcadero/PythonBlogExamples/tree/main/K_Means_Clustering_App
How to Create the Back-End by Implementing K-Means With SKlearn?
Once you’ve installed the necessary libraries, we are now ready to create our own K-Means class. Start by creating a new file called KMeans.py
in your project directory, import the cv2 library, and import KMeans
from sklearn
.
1 2 3 |
import cv2 from sklearn.cluster import KMeans |
Now create a class called KMeansClustering
with three functions, init
, load_image
, and apply
:
1 2 3 4 5 6 7 8 9 10 |
class KMeansClustering: def __init__(self): pass def load_image(self): pass def apply(self): pass |
First, let’s start by defining the init
function. Head over to the function and initialize the function with an additional parameter called K
. This will define the number of clusters to make in an image. Next, we will define some new variables. The self.K
variable will be used to define the number of clusters, whereas self.image
will be used to store our image. Here is what our init function looks like:
1 2 3 4 |
def __init__(self, K: int): self.K = K # Number of clusters for K-means algorithm self.image = None # Placeholder for the image array |
Next, for the load_image
function, all we need to do is load an image file from the system. To do this, we will define an additional parameter called filename
and then use the .imread()
method to load the image file. Here is what our load_image
function looks like:
1 2 3 |
def load_image(self, filename: str): self.image = cv2.imread(filename) # Load the image array using OpenCV |
Finally, let’s define our apply
function. We will start by converting the image in the self.image
variable from the BGR color space to the RGB color space. Next, we will reshape our image to produce a 2D array of pixels:
1 2 3 4 5 6 7 |
def apply(self): # Convert the image from BGR color space to RGB color space image_rgb = cv2.cvtColor(self.image, cv2.COLOR_BGR2RGB) # Reshape the image to a 2D array of pixels pixels = image_rgb.reshape(-1, 3) |
Once we’ve finished reformatting our image, we will apply the KMeans clustering algorithm and assign cluster labels to each pixel to create a segmented image. Finally, we will return the newly generated image. Here is what our apply function looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
def apply(self): # Convert the image from BGR color space to RGB color space image_rgb = cv2.cvtColor(self.image, cv2.COLOR_BGR2RGB) # Reshape the image to a 2D array of pixels pixels = image_rgb.reshape(-1, 3) # Apply K-means clustering algorithm kmeans = KMeans(n_clusters=self.K, random_state=42) kmeans.fit(pixels) labels = kmeans.labels_ centers = kmeans.cluster_centers_ # Assign cluster labels to each pixel in the image to create a segmented image segmented_image = centers[labels].reshape(image_rgb.shape) return segmented_image |
Here is what our KMeans.py
file looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import cv2 from sklearn.cluster import KMeans class KMeansClustering: def __init__(self, K: int): self.K = K # Number of clusters for K-means algorithm self.image = None # Placeholder for the image array def load_image(self, filename: str): self.image = cv2.imread(filename) # Load the image array using OpenCV def apply(self): # Convert the image from BGR color space to RGB color space image_rgb = cv2.cvtColor(self.image, cv2.COLOR_BGR2RGB) # Reshape the image to a 2D array of pixels pixels = image_rgb.reshape(-1, 3) # Apply K-means clustering algorithm kmeans = KMeans(n_clusters=self.K, random_state=42) kmeans.fit(pixels) labels = kmeans.labels_ centers = kmeans.cluster_centers_ # Assign cluster labels to each pixel in the image to create a segmented image segmented_image = centers[labels].reshape(image_rgb.shape) return segmented_image |
How to Create a Stunning GUI For the App?
Now that the backend of our app is ready, we can utilize the Delphi ecosystem to create a very attractive GUI for such an ML task.
Start by opening the Delphi CE application and creating a blank project by navigating to File > New > Multi-Device Application > Blank Application > Ok
. In this tutorial, we have named our project KMeansClustering
.
If you are not familiar with the various sections of the Delphi IDE, we recommend referring to our free eBook bundle, which covers the Delphi Python EcoSystem and all Python GUI offerings.
Let’s start by giving the form a name. Right-click on the form and select QuickEdit. Here, we will name our form MainForm
with the caption KMeansClustering App
.
Next, rename the source file of our MainForm
to Main.pas
. This will help us keep track of our project files. Now, let’s resize the form. So go to the Object Inspector and search for ClientWidth
and ClientHeight
in the properties tab. We will set them to 480
and 640
, respectively.
Now, let’s add a title to our app. Navigate to the standard palette and locate the TLabel
component. Drag and drop this component onto the form.
Next, right-click on the label and set the Name
as Title
with the Text
as KMeansClustering App
.
We will now modify the text style by using the TextSettings
property of the label. We will do this by navigating to the Object Inspector
and searching for TextSettings
. Now, click on the ellipses button (...
) next to the Font
property to see options for modifying the label based on your preferences. Like our other projects, we will set our font family as SemiBold Segoe UI. In addition, we will set the HorzAlign
and VertAlign
properties for our labels as Center
.
Here is what our form looks like:
Next, we will add a text field to allow the user to specify the number of clusters for the algorithm. So, head over to the Palette and search for the TEdit
component. Drag and drop this component into our form. Next, right-click on the component and Name
it as KValue
.
Here is what our form looks like:
Next, let’s add a few buttons to our form. For this, we will use the TButton
component, so navigate to the Palette and search for the component.
We will add two buttons, UploadButton
, to help us select the file, and an ApplyButton
, to help us apply the algorithm to our image.
Now, we will add a TOpenDialog
component, which will help us open a dialog box to select a file from our system. Open up the Palette and search for the component. Next, drag and drop this component anywhere into your form. The placement does not matter, as this component will be invisible.
Finally, let’s complete our form by adding image holders for our before and after Images. Head over to the Palette and search for the TImage
component. Add this component to your form.
Next, right-click on each component to define its name. Here we will set the left image as BeforeImage
and the right image as AfterImage
.
Now that our form is ready, let’s add a few final touches by adding style. To do this, you will need to download the free ebook bundle, which comes shipped with a multitude of styles that you can choose from.
Start by downloading your free ebook and extracting the FMX styles zip in the directory of your choosing. Next, select the style you want to use. Here we will be using AquaGraphite.style
available in the bundle.
To use this style, head to the Palette and add the TStyleBook
component to your form. Again, the placement does not matter for this component.
Double-click on the StyleBook1
component to open up your Style Designer. Next, click on the open button to open up a dialog box.
Now navigate to the .style
file of your choosing in the dialog box, select your file, and finally click on exit.
Once you’ve finalized your style, select the MainForm and head to the Object Inspector. Here we will search for the StyleBook property. Select the drop-down menu and select StyleBook1.
Here is what our final form looks like:
How to Export These Forms to Python Code?
Now that our project is complete, we only need to export it using the Delphi4Python exporter. However, exporting right now will cause the Upload and Apply buttons to lose their function. Therefore, we will need to add some functionality to each button in the form.
To do this, double-click on each button on the form. This will add an OnClick
method to that button. The procedure will be created in the .pas
file of the form. This allows you to add unique functionality to each button when clicked.
Because the Delphi4PythonExporter does not use run-time implementation, we must add at least one comment (//
) to each procedure to preserve the function when we export the form.
Now that our form is ready, we are ready to export. Select Tools > Export To Python > Export Current Entire Project
to export the project.
Here we will give the project the title KMeansClustering App
. Next, select the directory of your choosing and click on Export:
Because we had one form, Delphi will generate two Python files and one .pyfmx
file. The KMeansClustering.py
file will be used to run the application, whereas the Main.py
file contains the class for the MainForm
. The Main.pyfmx
file contains the visual information for the MainForm
. Here are the contents for each file.
KMeansClustering.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from delphifmx import * from Main import MainForm def main(): Application.Initialize() Application.Title = 'KMeansClustering App' Application.MainForm = MainForm(Application) Application.MainForm.Show() Application.Run() Application.MainForm.Destroy() if __name__ == '__main__': main() |
Main.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import os from delphifmx import * class MainForm(Form): def __init__(self, owner): self.Title = None self.KValue = None self.KLabel = None self.ApplyButton = None self.UploadButton = None self.OpenDialog1 = None self.BeforeImage = None self.AfterImage = None self.StyleBook1 = None self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "Main.pyfmx")) def ApplyButtonClick(self, Sender): pass def UploadButtonClick(self, Sender): pass |
How to Put it All Together Into a Fully Functional App?
Now that we have exported our project, all we need to do is bring it all together. Let’s start by opening up Main.py
in the text editor of your choice and importing some libraries:
1 2 3 4 5 |
# Additional Imports from KMeans import KMeansClustering from PIL import Image import numpy as np |
Next, let’s complete our UploadButton
. Head over to the UploadButtonClick
function and start by opening the file picker dialog box and filtering the files to show only the image files. Once the user selects the image, use the .Bitmap.LoadFromFile()
method to display it in the BeforeImage
placeholder. Our final UploadButtonClick
function looks like:
1 2 3 4 5 6 7 8 9 10 |
def UploadButtonClick(self, Sender): self.OpenDialog1.Title = "Select an Image" # Filtering only image formats to show for file pick self.OpenDialog1.Filter = "Image files (*.jpg;*.jpeg;*.png;*.webp)|*.jpg;*.jpeg;*.png;*.webp|All files (*.*)|*.*" if self.OpenDialog1.Execute(): # Load the selected image into BeforeImage self.BeforeImage.Bitmap.LoadFromFile(self.OpenDialog1.FileName) |
Next, let’s define our ApplyButtonClick
function. Start by creating an instance of our KMeansClustering
class and initialize it with the K
value from the KValue
edit box. Next, load the image using the load_image
method and apply the Kmeans clustering algorithm:
1 2 3 4 5 6 7 8 9 10 |
def ApplyButtonClick(self, Sender): # Create an instance of KMeansClustering kmeans = KMeansClustering(int(self.KValue.Text)) # Load the image from the stream in KMeansClustering kmeans.load_image(self.OpenDialog1.FileName) # Apply K-means clustering segmented_image = kmeans.apply() |
Now, simply convert the segmented image to a PIL Image and save the image in the same directory as the before image. Finally, show the image in the AfterImage
placeholder. Here is what our ApplyButtonClick
function looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
def ApplyButtonClick(self, Sender): # Create an instance of KMeansClustering kmeans = KMeansClustering(int(self.KValue.Text)) # Load the image from the stream in KMeansClustering kmeans.load_image(self.OpenDialog1.FileName) # Apply K-means clustering segmented_image = kmeans.apply() # Convert the segmented image array to PIL Image pil_image = Image.fromarray(segmented_image.astype(np.uint8)) # Save the image to the same directory as the before image output_path = os.path.join(os.path.dirname(self.OpenDialog1.FileName), "segmented_image.png") pil_image.save(output_path) # Load the segmented image in the AfterImage self.AfterImage.Bitmap.LoadFromFile(output_path) |
Here is what our final Main.py
file looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
import os from delphifmx import * # Additional Imports from KMeans import KMeansClustering from PIL import Image import numpy as np class MainForm(Form): def __init__(self, owner): self.Title = None self.KValue = None self.KLabel = None self.ApplyButton = None self.UploadButton = None self.OpenDialog1 = None self.BeforeImage = None self.AfterImage = None self.StyleBook1 = None self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "Main.pyfmx")) def ApplyButtonClick(self, Sender): # Create an instance of KMeansClustering kmeans = KMeansClustering(int(self.KValue.Text)) # Load the image from the stream in KMeansClustering kmeans.load_image(self.OpenDialog1.FileName) # Apply K-means clustering segmented_image = kmeans.apply() # Convert the segmented image array to PIL Image pil_image = Image.fromarray(segmented_image.astype(np.uint8)) # Save the image to the same directory as the before image output_path = os.path.join(os.path.dirname(self.OpenDialog1.FileName), "segmented_image.png") pil_image.save(output_path) # Load the segmented image in the AfterImage self.AfterImage.Bitmap.LoadFromFile(output_path) def UploadButtonClick(self, Sender): self.OpenDialog1.Title = "Select an Image" # Filtering only image formats to show for file pick self.OpenDialog1.Filter = "Image files (*.jpg;*.jpeg;*.png;*.webp)|*.jpg;*.jpeg;*.png;*.webp|All files (*.*)|*.*" if self.OpenDialog1.Execute(): # Load the selected image into BeforeImage self.BeforeImage.Bitmap.LoadFromFile(self.OpenDialog1.FileName) |
Now that our application is ready, let’s test it out. Head over to KMeansClustering.py
and run the file.
Let’s first define the KValue
as 3. Next, press the Upload button. This will open up a dialog box for your to select an image. Navigate to the directory of your image and open your image. Here we will be using a free stock image from Unsplash:
Once you’ve selected your image, it should appear on the BeforeImage
placeholder:
Now press the Apply button to evaluate your image. Your result image should appear in the AfterImage
placeholder:
Your file should also be saved in the same directory as your image:
Are You Ready to Create More Amazing GUIs With Delphi FMX?
In this tutorial, we have embarked on an exciting journey of creating a K-means clustering visualization app using Delphi FMX. We have explored the powerful capabilities of Delphi FMX and its seamless integration with the K-means algorithm, enabling us to develop an intuitive and interactive app. By empowering users with the ability to visualize and analyze their data, we can unlock valuable insights and make data-driven decisions.
What Are the Top FAQs Related to this Tutorial?
What is K-means clustering?
K-means clustering is an unsupervised machine learning algorithm that groups similar data points into clusters based on their feature similarity. It aims to minimize the sum of squared distances between the data points and their cluster centroids.
Why use Delphi for building a K-means clustering app?
Delphi is a powerful development platform that provides a rich ecosystem and GUI framework, such as FireMonkey (FMX), for creating visually appealing and interactive applications. It seamlessly integrates with Python, enabling you to leverage Python’s machine learning libraries and algorithms.
What is Delphi FMX?
Delphi FMX (FireMonkey) is a cross-platform GUI framework provided by Delphi. It allows you to develop visually stunning user interfaces with a single codebase that can run on multiple platforms, including Windows, macOS, iOS, and Android.
How can I integrate the K-means algorithm with Delphi FMX?
Delphi FMX integrates with Python through tools like the Delphi4PythonExporter, allowing you to write and execute Python code within your Delphi application. You can use Python’s scikit-learn library to implement the K-means algorithm and leverage its clustering capabilities.
Are there any specific data requirements for K-means clustering?
K-means clustering works with numerical data and requires a predefined number of clusters (K). Ensure your data is suitable for clustering by preprocessing it and selecting an appropriate value for K based on your specific application and dataset.