Close Menu
    Trending
    • Finding the right tool for the job: Visual Search for 1 Million+ Products | by Elliot Ford | Kingfisher-Technology | Jul, 2025
    • How Smart Entrepreneurs Turn Mid-Year Tax Reviews Into Long-Term Financial Wins
    • Become a Better Data Scientist with These Prompt Engineering Tips and Tricks
    • Meanwhile in Europe: How We Learned to Stop Worrying and Love the AI Angst | by Andreas Maier | Jul, 2025
    • Transform Complexity into Opportunity with Digital Engineering
    • OpenAI Is Fighting Back Against Meta Poaching AI Talent
    • Lessons Learned After 6.5 Years Of Machine Learning
    • Handling Big Git Repos in AI Development | by Rajarshi Karmakar | Jul, 2025
    AIBS News
    • Home
    • Artificial Intelligence
    • Machine Learning
    • AI Technology
    • Data Science
    • More
      • Technology
      • Business
    AIBS News
    Home»Artificial Intelligence»Real-Time Interactive Sentiment Analysis in Python
    Artificial Intelligence

    Real-Time Interactive Sentiment Analysis in Python

    Team_AIBS NewsBy Team_AIBS NewsMay 8, 2025No Comments10 Mins Read
    Share Facebook Twitter Pinterest LinkedIn Tumblr Reddit Telegram Email
    Share
    Facebook Twitter LinkedIn Pinterest Email


    what the very best a part of being an engineer is? You may simply construct stuff. It’s like a superpower. One wet afternoon I had this random concept of making a sentiment visualization of a textual content enter with a smiley face that adjustments it’s expression base on how constructive the textual content is. The extra constructive the textual content, the happier the smiley appears. There are some attention-grabbing ideas to study right here, so let me information you thru how this challenge works!

    Stipulations

    To observe alongside, you want the next packages:

    • customtkinter
    • Opencv-python
    • torch
    • transformers

    Utilizing uv, you possibly can add the dependencies with the next command:

    uv add customtkinter opencv-Python torch transformers

    NOTE: When utilizing uv with torch you’ll want to specify the index for the package deal. E.g if you wish to use cuda, you want the next in your pyproject.toml:

    [[tool.uv.index]]
    title = "pytorch-cu118"
    url = "https://obtain.pytorch.org/whl/cu118"
    express = true
    
    [tool.uv.sources]
    torch = [{ index = "pytorch-cu118" }]
    torchvision = [{ index = "pytorch-cu118" }]

    UI Structure Skeleton

    For some of these initiatives I all the time like to start out with a fast structure of the UI parts. On this case the structure shall be fairly easy, there’s a textbox with a single line on the high that fills the width and beneath it the canvas filling the remainder of the accessible area. This shall be the place we draw the smiley face 🙂

    Utilizing customtkinter, we are able to write the structure as follows:

    import customtkinter
    
    class App(customtkinter.CTk):
        def __init__(self) -> None:
            tremendous().__init__()
    
            self.title("Sentiment Analysis")
            self.geometry("800x600")
    
            self.grid_columnconfigure(0, weight=1)
            self.grid_rowconfigure(0, weight=0)
            self.grid_rowconfigure(1, weight=1)
    
            self.sentiment_text_var = customtkinter.StringVar(grasp=self, worth="Love")
    
            self.textbox = customtkinter.CTkEntry(
                grasp=self,
                corner_radius=10,
                font=("Consolas", 50),
                justify="heart",
                placeholder_text="Enter textual content right here...",
                placeholder_text_color="grey",
                textvariable=self.sentiment_text_var,
            )
            self.textbox.grid(row=0, column=0, padx=20, pady=20, sticky="nsew")
            self.textbox.focus()
    
            self.image_display = CTkImageDisplay(self)
            self.image_display.grid(row=1, column=0, padx=20, pady=20, sticky="nsew")

    Sadly there’s no good out of the field resolution for drawing opencv frames on a UI factor, so I constructed my very own CTkImageDisplay. If you wish to study intimately the way it works, take a look at my previous post. In brief, I take advantage of a CTKLabel element and decouple the thread that updates the picture from the GUI thread utilizing a synchronization queue.

    Procedural Smiley

    For our smiley face, we might use completely different discrete photos for sentiment ranges, so for instance having three photos saved for unfavorable, impartial and constructive. Nonetheless, to get a extra fine-grained sentiment visualized, we would want extra photos and it shortly turns into infeasible and we won’t be able to animate transitions between these photos.

    discrete sentiment smiley face images

    A greater method is to generate the picture of the smiley face procedurally at runtime. To maintain it easy, we’ll solely change the background coloration of the smiley, in addition to the curve of its mouth.

    continuous sentiment score smiley face images

    First we have to generate a canvas picture, on which we are able to draw the smiley.

    def create_sentiment_image(positivity: float, image_size: tuple[int, int]) -> np.ndarray:
        """
        Generates a sentiment picture primarily based on the positivity rating.
        This attracts a smiley with its expression primarily based on the positivity rating.
    
        Args:
            positivity: A float representing the positivity rating within the vary [-1, 1].
            image_size: A tuple representing the scale of the picture (width, peak).
    
        Returns:
            A string representing the trail to the generated sentiment picture.
        """
        width, peak = image_size
        body = np.zeros((peak, width, 4), dtype=np.uint8)
    
        # TODO: draw smiley
    
        return body

    Our picture must be clear outdoors of the smiley face, so we want 4 coloration channels, the final one would be the alpha channel. Since OpenCV photos are represented as numpy arrays with unsigned 8-bit integers, we create the picture utilizing the np.uint8 information kind. Do not forget that the arrays are saved y-first, so the peak of the image_size is handed first to the array creation

    We will outline some variables for the scale and colours of our smiley that shall be useful whereas drawing.

        color_outline = (80,) * 3 + (255,)  # grey
        thickness_outline = min(image_size) // 30
        heart = (width // 2, peak // 2)
        radius = min(image_size) // 2 - thickness_outline

    The background coloration of the smiley face must be purple for unfavorable sentiments and inexperienced for constructive sentiments. To attain this with a uniform brightness throughout the transition, we are able to use the HSV coloration area and easily interpolate the hue between 0% and 30%.

    color_bgr = color_hsv_to_bgr(
        hue=(positivity + 1) / 6, # positivity [-1,1] -> hue [0,1/3]
        saturation=0.5,
        worth=1,
    )
    color_bgra = color_bgr + (255,)

    We want to ensure to make the colour absolutely opaque by including a 100% alpha worth in fourth channel. Now we are able to draw our smiley face circle with a border.

    cv2.circle(body, heart, radius, color_bgra, -1) # Fill
    cv2.circle(body, heart, radius, color_outline, thickness_outline) # Border

    To date so good, now we are able to add the eyes. We calculate an offset from the middle to the left and proper to put the 2 eyes symmetrically.

    # calculate the place of the eyes
    eye_radius = radius // 5
    eye_offset_x = radius // 3
    eye_offset_y = radius // 4
    eye_left = (heart[0] - eye_offset_x, heart[1] - eye_offset_y)
    eye_right = (heart[0] + eye_offset_x, heart[1] - eye_offset_y)
    
    cv2.circle(body, eye_left, eye_radius, color_outline, -1)
    cv2.circle(body, eye_right, eye_radius, color_outline, -1)

    Now on to the difficult half, the mouth. The form of the mouth shall be a parabola scaled appropriately. We will merely multiply the usual parabola y=x² with the positivity rating.

    In the long run the road shall be drawn utilizing cv2.polylines, which wants xy coordinate pairs. Utilizing np.linspace we generate 100 factors on the x-axis and the polyval operate to calculate the in accordance y values of the polygon.

    # mouth parameters
    mouth_wdith = radius // 2
    mouth_height = radius // 3
    mouth_offset_y = radius // 3
    mouth_center_y = heart[1] + mouth_offset_y + positivity * mouth_height // 2
    mouth_left = (heart[0] - mouth_wdith, heart[1] + mouth_offset_y)
    mouth_right = (heart[0] + mouth_wdith, heart[1] + mouth_offset_y)
    
    # calculate factors of polynomial for the mouth
    ply_points_t = np.linspace(-1, 1, 100)
    ply_points_y = np.polyval([positivity, 0, 0], ply_points_t) # y=positivity*x²
    
    ply_points = np.array(
        [
            (
                mouth_left[0] + i * (mouth_right[0] - mouth_left[0]) / 100,
                mouth_center_y - ply_points_y[i] * mouth_height,
            )
            for i in vary(len(ply_points_y))
        ],
        dtype=np.int32,
    )
    
    # draw the mouth
    cv2.polylines(
        body,
        [ply_points],
        isClosed=False,
        coloration=color_outline,
        thickness=int(thickness_outline * 1.5),
    )

    Et voilà, we have now a procedural smiley face!

    To check the operate, I wrote a fast check case utilizing pytest that saves the smiley faces with completely different sentiment scores:

    from pathlib import Path
    
    import cv2
    import numpy as np
    import pytest
    
    from sentiment_analysis.utils import create_sentiment_image
    
    IMAGE_SIZE = (512, 512)
    
    
    @pytest.mark.parametrize(
        "positivity",
        np.linspace(-1, 1, 5),
    )
    def test_sentiments(visual_output_path: Path, positivity: float) -> None:
        """
        Take a look at the smiley face era.
        """
        picture = create_sentiment_image(positivity, IMAGE_SIZE)
    
        assert picture.form == (IMAGE_SIZE[1], IMAGE_SIZE[0], 4)
    
        # assert heart pixel is opaque
        assert picture[IMAGE_SIZE[1] // 2, IMAGE_SIZE[0] // 2, 3] == 255
    
        # save the picture for visible inspection
        positivity_num_0_100 = int((positivity + 1) * 50)
        image_fn = f"smiley_{positivity_num_0_100}.png"
        cv2.imwrite(str(visual_output_path / image_fn), picture)
    

    Sentiment Evaluation

    To find out how blissful or unhappy our smiley ought to appear to be, we first want to investigate the textual content enter and calculate a sentiment. This process is named sentiment evaluation. We are going to use a pre-trained transformer mannequin to foretell a classification rating for the lessons NEGATIVE, NEUTRAL and POSITIVE. We will then fuse the arrogance scores of those lessons to calculate a ultimate sentiment rating between -1 and +1.

    Utilizing the pipeline from the transformers library, we are able to outline processing pipeline primarily based on a pre-trained model from huggingface. Utilizing the top_k parameter, we are able to specify what number of classification outcomes must be returned. Since we wish all three lessons, we set it to three.

    from transformers import pipeline
    
    model_name = "cardiffnlp/twitter-roberta-base-sentiment"
    
    sentiment_pipeline = pipeline(
        process="sentiment-analysis",
        mannequin=model_name,
        top_k=3,
    )

    To run the sentiment evaluation, we are able to name the pipeline with a string argument. This can return an inventory of outcomes with a single factor, so we have to unpack the primary factor.

    outcomes = self.sentiment_pipeline(textual content)
    
    # [
    #     [
    #         {"label": "LABEL_2", "score": 0.5925878286361694},
    #         {"label": "LABEL_1", "score": 0.3553399443626404},
    #         {"label": "LABEL_0", "score": 0.05207228660583496},
    #     ]
    # ]
    
    for label_score_dict in outcomes[0]:
        label: str = label_score_dict["label"]
        rating: float = label_score_dict["score"]

    We will outline a label mapping, that tells us how every confidence rating impacts the ultimate sentiment. Then we are able to combination the positivity over all confidence scores.

    label_mapping = {"LABEL_0": -1, "LABEL_1": 0, "LABEL_2": 1}
    
    positivity = 0.0
    for label_score_dict in outcomes[0]:
        label: str = label_score_dict["label"]
        rating: float = label_score_dict["score"]
    
        if label in label_mapping:
            positivity += label_mapping[label] * rating

    To check our pipeline, we are able to wrap it in a category and run some checks utilizing pytest. We confirm that sentences with a constructive sentiment have a rating better than zero and vice versa sentences with a unfavorable sentiment ought to have a rating beneath zero.

    import pytest
    
    from sentiment_analysis.sentiment_pipeline import SentimentAnalysisPipeline
    
    
    @pytest.fixture
    def sentiment_pipeline() -> SentimentAnalysisPipeline:
        """
        Fixture to create a SentimentAnalysisPipeline occasion.
        """
        return SentimentAnalysisPipeline(
            model_name="cardiffnlp/twitter-roberta-base-sentiment",
            label_mapping={"LABEL_0": -1.0, "LABEL_1": 0.0, "LABEL_2": 1.0},
        )
    
    
    @pytest.mark.parametrize(
        "text_input",
        [
            "I love this!",
            "This is awesome!",
            "I am so happy!",
            "This is the best day ever!",
            "I am thrilled with the results!",
        ],
    )
    def test_sentiment_analysis_pipeline_positive(
        sentiment_pipeline: SentimentAnalysisPipeline, text_input: str
    ) -> None:
        """
        Take a look at the sentiment evaluation pipeline with a constructive enter.
        """
        assert (
            sentiment_pipeline.run(text_input) > 0.0
        ), "Anticipated constructive sentiment rating."
    
    
    @pytest.mark.parametrize(
        "text_input",
        [
            "I hate this!",
            "This is terrible!",
            "I am so sad!",
            "This is the worst day ever!",
            "I am disappointed with the results!",
        ],
    )
    def test_sentiment_analysis_pipeline_negative(
        sentiment_pipeline: SentimentAnalysisPipeline, text_input: str
    ) -> None:
        """
        Take a look at the sentiment evaluation pipeline with a unfavorable enter.
        """
        assert (
            sentiment_pipeline.run(text_input) < 0.0
        ), "Anticipated unfavorable sentiment rating."
    

    Integration

    Now the final half that’s lacking, is solely hooking up the textual content field to our sentiment pipeline and updating the displayed picture with the corresponding smiley face. We will add a hint to the textual content variable, which can run the sentiment pipeline in a brand new thread managed by a thread pool, to stop the UI from freezing whereas the pipeline is working.

    class App(customtkinter.CTk):
        def __init__(self, sentiment_analysis_pipeline: SentimentAnalysisPipeline) -> None:
            tremendous().__init__()
            self.sentiment_analysis_pipeline = sentiment_analysis_pipeline
    
            ...
    
            self.sentiment_image = None
    
            self.sentiment_text_var = customtkinter.StringVar(grasp=self, worth="Love")
            self.sentiment_text_var.trace_add("write", lambda *_: self.on_sentiment_text_changed())
    
            ...
    
            self.update_sentiment_pool = ThreadPool(processes=1)
    
            self.on_sentiment_text_changed()
    
        def on_sentiment_text_changed(self) -> None:
            """
            Callback operate to deal with textual content adjustments within the textbox.
            """
            new_text = self.sentiment_text_var.get()
    
            self.update_sentiment_pool.apply_async(
                self._update_sentiment,
                (new_text,),
            )
    
        def _update_sentiment(self, new_text: str) -> None:
            """
            Replace the sentiment picture primarily based on the brand new textual content enter.
            This operate is run in a separate course of to keep away from blocking the primary thread.
    
            Args:
                new_text: The brand new textual content enter from the person.
            """
            positivity = self.sentiment_analysis_pipeline.run(new_text)
    
            self.sentiment_image = create_sentiment_image(
                positivity,
                self.image_display.display_size,
            )
    
            self.image_display.update_frame(self.sentiment_image)
    
    
    def important() -> None:
        # Initialize the sentiment evaluation pipeline
        sentiment_analysis = SentimentAnalysisPipeline(
            model_name="cardiffnlp/twitter-roberta-base-sentiment",
            label_mapping={"LABEL_0": -1, "LABEL_1": 0, "LABEL_2": 1},
        )
    
        app = App(sentiment_analysis)
        app.mainloop()
    

    And eventually the smiley is visualized within the software and adjustments dynamically with the sentiment of the textual content enter!



    For the total implementation and extra particulars, checkout the challenge repository on GitHub:

    https://github.com/trflorian/sentiment-analysis-viz


    All visualizations on this put up have been created by the writer.



    Source link

    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    Previous ArticleEfficient Reasoning in Large Language Models: A Structured Survey | by Chandini Saisri Uppuganti | May, 2025
    Next Article Why Solopreneurs Should Think Like Startup Founders
    Team_AIBS News
    • Website

    Related Posts

    Artificial Intelligence

    Become a Better Data Scientist with These Prompt Engineering Tips and Tricks

    July 1, 2025
    Artificial Intelligence

    Lessons Learned After 6.5 Years Of Machine Learning

    July 1, 2025
    Artificial Intelligence

    Prescriptive Modeling Makes Causal Bets – Whether You Know it or Not!

    June 30, 2025
    Add A Comment
    Leave A Reply Cancel Reply

    Top Posts

    Finding the right tool for the job: Visual Search for 1 Million+ Products | by Elliot Ford | Kingfisher-Technology | Jul, 2025

    July 1, 2025

    I Tried Buying a Car Through Amazon: Here Are the Pros, Cons

    December 10, 2024

    Amazon and eBay to pay ‘fair share’ for e-waste recycling

    December 10, 2024

    Artificial Intelligence Concerns & Predictions For 2025

    December 10, 2024

    Barbara Corcoran: Entrepreneurs Must ‘Embrace Change’

    December 10, 2024
    Categories
    • AI Technology
    • Artificial Intelligence
    • Business
    • Data Science
    • Machine Learning
    • Technology
    Most Popular

    Richard L. Garwin, a Creator of the Hydrogen Bomb, Dies at 97

    May 14, 2025

    Free Webinar | May 1: How to Create Stories That Elevate Your Brand

    April 10, 2025

    Gradients, is the best performing AutoLLM platform in the world. | by WanderingWeights | Apr, 2025

    April 6, 2025
    Our Picks

    Finding the right tool for the job: Visual Search for 1 Million+ Products | by Elliot Ford | Kingfisher-Technology | Jul, 2025

    July 1, 2025

    How Smart Entrepreneurs Turn Mid-Year Tax Reviews Into Long-Term Financial Wins

    July 1, 2025

    Become a Better Data Scientist with These Prompt Engineering Tips and Tricks

    July 1, 2025
    Categories
    • AI Technology
    • Artificial Intelligence
    • Business
    • Data Science
    • Machine Learning
    • Technology
    • Privacy Policy
    • Disclaimer
    • Terms and Conditions
    • About us
    • Contact us
    Copyright © 2024 Aibsnews.comAll Rights Reserved.

    Type above and press Enter to search. Press Esc to cancel.