<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ardhansu Das</title>
    <description>The latest articles on DEV Community by Ardhansu Das (@ardhansu).</description>
    <link>https://dev.to/ardhansu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3130520%2F5488d0df-e8e1-4088-8b3b-8cba998a66ec.jpg</url>
      <title>DEV Community: Ardhansu Das</title>
      <link>https://dev.to/ardhansu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ardhansu"/>
    <language>en</language>
    <item>
      <title>Integrating the OpenAI API the Right Way — Streaming, Rate-Limiting, and Prompt</title>
      <dc:creator>Ardhansu Das</dc:creator>
      <pubDate>Wed, 08 Jul 2026 06:35:15 +0000</pubDate>
      <link>https://dev.to/ardhansu/integrating-the-openai-api-the-right-way-streaming-rate-limiting-and-prompt-1ml9</link>
      <guid>https://dev.to/ardhansu/integrating-the-openai-api-the-right-way-streaming-rate-limiting-and-prompt-1ml9</guid>
      <description>&lt;p&gt;Integrating the OpenAI API the Right Way&lt;br&gt;
Calling openai.chat.completions.create() is the easy 10% of building an AI-powered product. The hard 90% is making it feel instant, not breaking under load, and getting consistent output from a model that's fundamentally non-deterministic. I ran into all three of these while building an AI tool that generates formal letters from user input using GPT.&lt;br&gt;
Here's what actually mattered.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Streaming isn't optional for UX
If you're generating anything longer than a sentence, a blocking request feels broken — users stare at a spinner for 5-10 seconds with no feedback. Streaming turns that dead time into something that reads like the model is "thinking out loud," which massively changes perceived performance even though total latency is the same.
javascriptconst stream = await openai.chat.completions.create({
model: "gpt-3.5-turbo",
messages: [{ role: "user", content: prompt }],
stream: true,
});&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;for await (const chunk of stream) {&lt;br&gt;
  const token = chunk.choices[0]?.delta?.content || "";&lt;br&gt;
  process.stdout.write(token); // or push to a WebSocket/SSE connection&lt;br&gt;
}&lt;br&gt;
On the frontend, this pairs naturally with Server-Sent Events or a WebSocket connection so tokens render as they arrive instead of waiting for the full response.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Rate-limiting protects you, not just OpenAI
It's tempting to think rate-limiting is only about respecting OpenAI's API limits. In practice, it's just as much about protecting your infrastructure and your bill from a single user (or a bug in your own retry logic) hammering the endpoint.
A simple token-bucket approach per user goes a long way:
javascriptconst buckets = new Map();&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;function allowRequest(userId, limit = 5, windowMs = 60_000) {&lt;br&gt;
  const now = Date.now();&lt;br&gt;
  const bucket = buckets.get(userId) || { count: 0, resetAt: now + windowMs };&lt;/p&gt;

&lt;p&gt;if (now &amp;gt; bucket.resetAt) {&lt;br&gt;
    bucket.count = 0;&lt;br&gt;
    bucket.resetAt = now + windowMs;&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;if (bucket.count &amp;gt;= limit) return false;&lt;/p&gt;

&lt;p&gt;bucket.count += 1;&lt;br&gt;
  buckets.set(userId, bucket);&lt;br&gt;
  return true;&lt;br&gt;
}&lt;br&gt;
For production, swap the in-memory Map for Redis so limits hold up across multiple server instances — an in-memory bucket resets the moment you scale horizontally.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Prompt templates need version control, not vibes
Once you have more than two or three prompts, "tweak it until it feels right" stops scaling. What worked well was treating prompt templates as versioned, parameterized objects rather than inline strings scattered across the codebase:
javascriptconst templates = {
formalLetter: {
version: "v3",
system: "You are a professional correspondence writer. Be concise, formal, and grammatically precise.",
build: ({ recipient, purpose, tone }) =&amp;gt;
  &lt;code&gt;Write a formal letter to ${recipient} regarding ${purpose}. Tone: ${tone}.&lt;/code&gt;,
},
// ...9 more templates
};
This made it possible to A/B test prompt changes, roll back a regression instantly, and keep a clean diff history of why a prompt changed — something you lose completely when prompts are just strings buried in route handlers.&lt;/li&gt;
&lt;li&gt;Treat the model's output as untrusted input
This one's easy to skip until it bites you. Model output can include unexpected formatting, occasional hallucinated details, or — if you're not careful with your system prompt — instructions the user tried to sneak into the input. Always:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sanitize before rendering (especially if output ever touches HTML)&lt;br&gt;
Validate structure if you expect JSON (models drift; don't trust it blindly)&lt;br&gt;
Set a max_tokens ceiling so a runaway generation doesn't blow your latency or cost budget&lt;/p&gt;

&lt;p&gt;javascripttry {&lt;br&gt;
  const response = await openai.chat.completions.create({&lt;br&gt;
    model: "gpt-3.5-turbo",&lt;br&gt;
    messages,&lt;br&gt;
    max_tokens: 800,&lt;br&gt;
  });&lt;br&gt;
  const content = response.choices[0].message.content;&lt;br&gt;
  // sanitize/validate before using &lt;code&gt;content&lt;/code&gt;&lt;br&gt;
} catch (err) {&lt;br&gt;
  // handle rate limit (429), timeout, and malformed-response cases separately&lt;br&gt;
}&lt;br&gt;
The takeaway&lt;br&gt;
None of this is exotic — it's the same discipline you'd apply to any third-party API. But it's easy to skip when a demo works fine with one user and no load. The gap between "works in a demo" and "works in production" for LLM features is almost entirely streaming, rate-limiting, and prompt versioning — not the model call itself.&lt;/p&gt;

&lt;p&gt;I write about backend systems, applied AI, and the engineering details that don't make it into the docs.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>openai</category>
      <category>ux</category>
    </item>
    <item>
      <title>Building an NLP Pipeline That Actually Understands Offer Text (with spaCy)</title>
      <dc:creator>Ardhansu Das</dc:creator>
      <pubDate>Wed, 08 Jul 2026 06:34:21 +0000</pubDate>
      <link>https://dev.to/ardhansu/building-an-nlp-pipeline-that-actually-understands-offer-text-with-spacy-2dg9</link>
      <guid>https://dev.to/ardhansu/building-an-nlp-pipeline-that-actually-understands-offer-text-with-spacy-2dg9</guid>
      <description>&lt;p&gt;Building an NLP Pipeline That Actually Understands Offer Text&lt;br&gt;
Most "extract structured data from unstructured text" tutorials stop at named entity recognition and call it a day. In practice, that's maybe 30% of the problem. The real work is building a pipeline that can reliably pull out conditional information — things like "eligible only for orders above ₹999" or "valid till stocks last" — from messy, inconsistent text scraped off the web.&lt;br&gt;
Here's how I approached this while building an NLP pipeline to extract eligibility conditions and offer insights from scraped promotional text.&lt;br&gt;
The problem with naive NER&lt;br&gt;
Out-of-the-box spaCy models are great at tagging ORG, MONEY, DATE, and PERCENT entities. But offer text isn't clean prose — it's fragments, abbreviations, and domain-specific phrasing:&lt;br&gt;
"Flat 20% off* | Min order ₹499 | T&amp;amp;C apply | Valid on select cards only"&lt;br&gt;
A generic model will happily tag 20% and ₹499 as entities, but it has no idea that one is a discount and the other is a threshold condition, or that "select cards only" is a restriction that changes the entire meaning of the offer.&lt;br&gt;
Combining rule-based parsing with entity extraction&lt;br&gt;
The fix isn't to throw more data at a bigger model — it's to combine spaCy's statistical NER with rule-based matching for domain-specific patterns:&lt;br&gt;
pythonimport spacy&lt;br&gt;
from spacy.matcher import Matcher&lt;/p&gt;

&lt;p&gt;nlp = spacy.load("en_core_web_sm")&lt;br&gt;
matcher = Matcher(nlp.vocab)&lt;/p&gt;

&lt;h1&gt;
  
  
  Pattern: "min order" / "minimum order" followed by a currency amount
&lt;/h1&gt;

&lt;p&gt;min_order_pattern = [&lt;br&gt;
    {"LOWER": {"IN": ["min", "minimum"]}},&lt;br&gt;
    {"LOWER": "order", "OP": "?"},&lt;br&gt;
    {"IS_CURRENCY": True, "OP": "?"},&lt;br&gt;
    {"LIKE_NUM": True}&lt;br&gt;
]&lt;br&gt;
matcher.add("MIN_ORDER", [min_order_pattern])&lt;/p&gt;

&lt;p&gt;def extract_conditions(text):&lt;br&gt;
    doc = nlp(text)&lt;br&gt;
    matches = matcher(doc)&lt;br&gt;
    conditions = []&lt;br&gt;
    for match_id, start, end in matches:&lt;br&gt;
        span = doc[start:end]&lt;br&gt;
        conditions.append(span.text)&lt;br&gt;
    return conditions&lt;br&gt;
This gets you a huge accuracy boost on structured sub-phrases without needing a labeled dataset or fine-tuning a transformer.&lt;br&gt;
Where entity extraction still earns its keep&lt;br&gt;
Rule-based matching handles known patterns well, but you still need statistical NER for the long tail — brand names, card issuer names, dates written in inconsistent formats. The trick is layering them:&lt;/p&gt;

&lt;p&gt;Rule-based matcher — catches conditions, thresholds, restrictions (high precision, domain-specific)&lt;br&gt;
Statistical NER — catches entities you can't enumerate in advance (brands, dates, amounts)&lt;br&gt;
Post-processing merge — resolves overlaps and attaches conditions to the entities they modify&lt;/p&gt;

&lt;p&gt;pythondef parse_offer(text):&lt;br&gt;
    doc = nlp(text)&lt;br&gt;
    entities = [(ent.text, ent.label_) for ent in doc.ents]&lt;br&gt;
    conditions = extract_conditions(text)&lt;br&gt;
    return {&lt;br&gt;
        "entities": entities,&lt;br&gt;
        "conditions": conditions,&lt;br&gt;
        "raw": text&lt;br&gt;
    }&lt;br&gt;
Lessons that don't show up in the docs&lt;br&gt;
A few things that saved a lot of debugging time:&lt;/p&gt;

&lt;p&gt;Normalize before you tag. Scraped text has inconsistent casing, stray HTML entities, and unicode symbols like ₹ that trip up tokenizers if you don't clean them first.&lt;br&gt;
Version your matcher patterns. As you scrape more sources, you'll keep discovering new phrasings. Treat your rule set like code — test it, don't just append to it.&lt;br&gt;
Precision over recall for conditions. A false positive (extracting a wrong condition) is worse than a missed one, since downstream systems often act on these conditions automatically.&lt;/p&gt;

&lt;p&gt;Why this matters beyond offers&lt;br&gt;
The same layered approach — statistical NER for open-ended entities, rule-based matching for domain patterns, and a merge step to reconcile them — generalizes to almost any "extract structured facts from semi-structured text" problem: parsing job postings, extracting clauses from contracts, or pulling structured fields out of support tickets.&lt;br&gt;
If you're building something similar, I'd genuinely recommend starting with the rule-based layer before reaching for a fine-tuned model. It's faster to iterate on, easier to debug, and often gets you 80% of the way there for a fraction of the engineering cost.&lt;/p&gt;

&lt;p&gt;I write about backend systems, NLP, and applied ML. Follow along for more.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why Data Structures Still Matter When You're Doing Machine Learning</title>
      <dc:creator>Ardhansu Das</dc:creator>
      <pubDate>Wed, 08 Jul 2026 06:32:50 +0000</pubDate>
      <link>https://dev.to/ardhansu/why-data-structures-still-matter-when-youre-doing-machine-learning-4e2k</link>
      <guid>https://dev.to/ardhansu/why-data-structures-still-matter-when-youre-doing-machine-learning-4e2k</guid>
      <description>&lt;p&gt;It's easy to assume DSA is "just for interviews" once you're writing model.fit() and letting a library handle the rest. But the moment your ML system has to run on real, large-scale, latency-sensitive data — not a clean Kaggle CSV — data structures and complexity analysis stop being theoretical and start being the difference between a system that scales and one that falls over.&lt;br&gt;
A few places where this showed up directly in projects I've built.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Preprocessing at scale is a data structures problem
Feature engineering on large datasets is full of classic DSA patterns hiding in plain sight:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Deduplication of scraped or user-submitted records → hash sets, O(n) instead of O(n²) pairwise comparison&lt;br&gt;
Sliding-window features (rolling averages, time-based aggregations) → deques for O(1) amortized window updates instead of recomputing from scratch&lt;br&gt;
Frequency-based features (word counts, category counts for encoding) → hash maps, but watch out for high-cardinality categorical features blowing up memory&lt;/p&gt;

&lt;p&gt;pythonfrom collections import deque&lt;/p&gt;

&lt;p&gt;def rolling_average(stream, window_size):&lt;br&gt;
    window = deque(maxlen=window_size)&lt;br&gt;
    for value in stream:&lt;br&gt;
        window.append(value)&lt;br&gt;
        yield sum(window) / len(window)&lt;br&gt;
A naive rolling average recomputed from a slice on every step is O(n·k). The deque version is O(n) total. On a dataset with millions of rows, that's the difference between a preprocessing job that finishes in minutes versus one that doesn't finish at all.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Graphs show up more than you'd expect&lt;br&gt;
Any time your data has relationships — user-item interactions, dependency chains, entity co-occurrence — you're working with a graph whether you call it that or not. Recommendation systems, fraud-detection pipelines, and even NLP dependency parsing all lean on graph traversal and shortest-path concepts:&lt;br&gt;
pythondef bfs_connected_component(graph, start):&lt;br&gt;
visited = {start}&lt;br&gt;
queue = deque([start])&lt;br&gt;
component = []&lt;/p&gt;

&lt;p&gt;while queue:&lt;br&gt;
    node = queue.popleft()&lt;br&gt;
    component.append(node)&lt;br&gt;
    for neighbor in graph[node]:&lt;br&gt;
        if neighbor not in visited:&lt;br&gt;
            visited.add(neighbor)&lt;br&gt;
            queue.append(neighbor)&lt;/p&gt;

&lt;p&gt;return component&lt;br&gt;
Understanding why BFS is O(V + E) — not just being able to write it — matters when you're deciding whether a graph-based feature is even feasible to compute on a graph with millions of edges.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Complexity analysis decides your architecture, not just your code&lt;br&gt;
This is the part that's easy to underrate. Knowing Big-O isn't just about passing a coding interview — it directly informs decisions like:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Whether to precompute and cache a similarity matrix (O(n²) space) or compute similarities on demand&lt;br&gt;
Whether a k-nearest-neighbors lookup needs an approximate structure (KD-tree, ball tree, or an ANN library) once your dataset crosses a certain size, because brute-force O(n) search per query stops being viable&lt;br&gt;
Whether a batch job's O(n log n) sort-and-merge step will actually finish inside your maintenance window as data grows&lt;/p&gt;

&lt;p&gt;None of these are "algorithm interview" questions. They're architecture decisions that determine whether your ML pipeline runs in 10 minutes or 10 hours next quarter when the dataset doubles.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A concrete example: efficient top-k without sorting everything
A common ML pipeline task — get the top-k highest-scoring items from a large candidate set — gets solved wrong surprisingly often:
pythonimport heapq&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;def top_k(candidates, k):&lt;br&gt;
    # candidates: list of (score, item) tuples&lt;br&gt;
    return heapq.nlargest(k, candidates, key=lambda x: x[0])&lt;br&gt;
Sorting the entire candidate list is O(n log n). A heap-based nlargest is O(n log k) — a meaningful difference when n is in the millions and k is small, which is exactly the shape of most recommendation and ranking problems.&lt;br&gt;
The takeaway&lt;br&gt;
Libraries like scikit-learn and TensorFlow abstract away a lot, but they don't abstract away the cost of how you get data into and out of them. The preprocessing, feature engineering, and serving layers around a model are still ordinary software engineering — and that's where DSA fundamentals quietly decide whether your ML system is production-ready or just a notebook that happens to work on a laptop.&lt;/p&gt;

&lt;p&gt;I write about backend systems, applied ML, and the engineering fundamentals that hold it all together.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>dsa</category>
      <category>machinelearning</category>
      <category>python</category>
    </item>
    <item>
      <title>🧠 Deep Learning: Or How I Learned to Stop Worrying and Love the Matrix Multiplication</title>
      <dc:creator>Ardhansu Das</dc:creator>
      <pubDate>Mon, 12 May 2025 06:52:08 +0000</pubDate>
      <link>https://dev.to/ardhansu/deep-learning-or-how-i-learned-to-stop-worrying-and-love-the-matrix-multiplication-h1i</link>
      <guid>https://dev.to/ardhansu/deep-learning-or-how-i-learned-to-stop-worrying-and-love-the-matrix-multiplication-h1i</guid>
      <description>&lt;p&gt;Welcome to the magical, GPU-heated world of Deep Learning — where we teach machines to think, sort of, by throwing math, data, and a terrifying number of layers at them until they give us something cool like a cat detector or ChatGPT.&lt;/p&gt;

&lt;p&gt;Let’s be honest: deep learning sounds like something you'd do during therapy. But no — it’s just machine learning’s more expensive, more dramatic sibling who needs a Tesla V100 GPU to feel alive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🤖 What Is Deep Learning?&lt;/strong&gt;&lt;br&gt;
Deep Learning is like that student who didn’t pay attention all semester but still aces the final because they “intuitively figured it out.” Instead of writing rules, we throw data at neural networks and let them figure things out on their own. And somehow, they do. Sort of.&lt;/p&gt;

&lt;p&gt;At the heart of it are neural networks, which are vaguely inspired by the human brain — if your brain only did matrix multiplication and silently judged your batch size choices.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;🧱 The Building Blocks of a Modern Deep Learning Breakdown:&lt;br&gt;
*&lt;/em&gt;🔹 1. Neurons and Layers&lt;br&gt;
A neuron in deep learning is a function that says: “Give me a number, and I’ll pass it through this mystical activation function until it looks fancy.”&lt;/p&gt;

&lt;p&gt;Stack these neurons into layers. Stack those layers into models. Stack those models into an identity crisis when the loss doesn't converge.&lt;/p&gt;

&lt;p&gt;🔹 2. Activation Functions&lt;br&gt;
You’ve probably heard of ReLU — the one that just zeroes out negative numbers like a savage. There’s also sigmoid and tanh, which are great if you're nostalgic for the 90s and vanishing gradients.&lt;/p&gt;

&lt;p&gt;🔹 3. Loss Function&lt;br&gt;
This is literally the model’s “How wrong am I?” function. The goal is to minimize loss, but most of the time it just minimizes your will to debug.&lt;/p&gt;

&lt;p&gt;🔹 4. Backpropagation&lt;br&gt;
Imagine teaching a dog to sit by yelling “no” every time it gets it wrong, but instead of a dog it’s math, and instead of “no” it’s derivatives.&lt;/p&gt;

&lt;p&gt;**🧪 So, What Have I Done With Deep Learning?&lt;br&gt;
**Oh, you know — just the usual:&lt;/p&gt;

&lt;p&gt;Built a face mask detection system using ResNet50, because if you’re not using a heavyweight model to check for tiny strips of fabric on faces, are you even doing deep learning?&lt;/p&gt;

&lt;p&gt;Fiddled with OpenCV until my webcam gave me PTSD.&lt;/p&gt;

&lt;p&gt;Watched training loss go down like my hopes and dreams… only to watch validation accuracy crash like my laptop running 50 epochs.&lt;/p&gt;

&lt;p&gt;**🧩 Why Is Deep Learning So Hard Yet Addictive?&lt;br&gt;
**Because there's always that 1% chance that after 7 hours of training and 8 Red Bulls, your model might actually work. And when it does? You feel like an AI god. Until it classifies a banana as a gun. Again.&lt;/p&gt;

&lt;p&gt;**📈 Final Thoughts (Because This Blog Needs a Conclusion)&lt;br&gt;
**Deep learning is a lot like dating: it requires patience, constant tweaking, and sometimes ends in heartbreak because “the weights didn’t align.” But if you keep at it, feed it enough data, and don’t mind being ghosted by your GPU, it can actually do some amazing things.&lt;/p&gt;

&lt;p&gt;So, here’s to the next model. The next dataset. The next long night spent tuning hyperparameters only to realize… you forgot to normalize your inputs. Again.&lt;/p&gt;

&lt;p&gt;Stay caffeinated, stay curious, and may your gradients never vanish.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>AI Meets Safety: Real-Time Face Mask Detection with Python</title>
      <dc:creator>Ardhansu Das</dc:creator>
      <pubDate>Tue, 06 May 2025 17:44:24 +0000</pubDate>
      <link>https://dev.to/ardhansu/ai-meets-safety-real-time-face-mask-detection-with-python-3ol7</link>
      <guid>https://dev.to/ardhansu/ai-meets-safety-real-time-face-mask-detection-with-python-3ol7</guid>
      <description>&lt;p&gt;In the post-pandemic world, face masks have become essential. As a Full-Stack Developer exploring AI and Computer Vision, I decided to build a real-time face mask detection system using Python, OpenCV, and Deep Learning.&lt;/p&gt;

&lt;p&gt;Here’s a breakdown of how I built it and what I learned.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🚀 Project Overview&lt;/strong&gt;&lt;br&gt;
The project captures live video from your webcam and uses a trained deep learning model (MobileNetV2) to determine if a person is wearing a mask or not. The model then overlays a label on the video feed in real-time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧠 Tools &amp;amp; Technologies Used&lt;br&gt;
Python&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenCV – for video capture and image processing&lt;/p&gt;

&lt;p&gt;TensorFlow/Keras – for training the model&lt;/p&gt;

&lt;p&gt;MobileNetV2 – a lightweight CNN model for fast inference&lt;/p&gt;

&lt;p&gt;Matplotlib &amp;amp; NumPy – for data analysis and preprocessing&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🛠️ How It Works&lt;/strong&gt;&lt;br&gt;
Data Collection&lt;br&gt;
I used a dataset with two categories: with mask and without mask. You can find such datasets on Kaggle or build your own.&lt;/p&gt;

&lt;p&gt;Model Training&lt;br&gt;
I used MobileNetV2 as the base model and fine-tuned it with our dataset. After several epochs, the model reached over 95% accuracy.&lt;/p&gt;

&lt;p&gt;Face Detection&lt;br&gt;
Using OpenCV’s built-in face detector (cv2.CascadeClassifier), we detect faces in each video frame.&lt;/p&gt;

&lt;p&gt;Prediction &amp;amp; Display&lt;br&gt;
Each detected face is passed to the model. Based on the output, a green label (“Mask”) or red label (“No Mask”) is drawn on the frame.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📦 Key Learnings&lt;/strong&gt;&lt;br&gt;
Real-time applications require optimization — MobileNetV2 helped due to its lightweight architecture.&lt;/p&gt;

&lt;p&gt;OpenCV is powerful for computer vision tasks, and integrating it with deep learning opens up many possibilities.&lt;/p&gt;

&lt;p&gt;Proper dataset preparation (balanced, augmented, preprocessed) significantly boosts model performance.&lt;/p&gt;

&lt;p&gt;📁 GitHub Repository&lt;br&gt;
You can find the full code and instructions &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ardhansu" rel="noopener noreferrer"&gt;
        ardhansu
      &lt;/a&gt; / &lt;a href="https://github.com/ardhansu/Face-Mask-Detection" rel="noopener noreferrer"&gt;
        Face-Mask-Detection
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;📌 Final Thoughts&lt;br&gt;
This was my first step into combining computer vision and deep learning for something impactful. It’s exciting to see how AI can be used in practical, real-time applications like this.&lt;/p&gt;

&lt;p&gt;I’d love to hear your feedback! Let me know if you build on this or have suggestions for improvements. 👇&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
