<?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: Han Lou</title>
    <description>The latest articles on DEV Community by Han Lou (@han_lou_493c3fecccc66c1f0).</description>
    <link>https://dev.to/han_lou_493c3fecccc66c1f0</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%2F4185797%2F5700eb97-5e90-470b-979c-6937955b00d1.png</url>
      <title>DEV Community: Han Lou</title>
      <link>https://dev.to/han_lou_493c3fecccc66c1f0</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/han_lou_493c3fecccc66c1f0"/>
    <language>en</language>
    <item>
      <title>I ran a million Secret Santa draws through my generator. Here's what the paper hat gets wrong</title>
      <dc:creator>Han Lou</dc:creator>
      <pubDate>Mon, 02 Nov 2026 02:09:31 +0000</pubDate>
      <link>https://dev.to/han_lou_493c3fecccc66c1f0/i-ran-a-million-secret-santa-draws-through-my-generator-heres-what-the-paper-hat-gets-wrong-5820</link>
      <guid>https://dev.to/han_lou_493c3fecccc66c1f0/i-ran-a-million-secret-santa-draws-through-my-generator-heres-what-the-paper-hat-gets-wrong-5820</guid>
      <description>&lt;p&gt;I run a small &lt;a href="https://secretsantagenerator.xyz/" rel="noopener noreferrer"&gt;Secret Santa generator&lt;/a&gt;. Before this year's rush I wanted two things: proof that its draw is actually fair, and real numbers for the problems people hit when they draw names from a hat. So I took the draw module the server runs (TypeScript, about 400 lines), ran it in Node on a laptop and counted what came out.&lt;/p&gt;

&lt;p&gt;Every simulated draw below got a fresh 128-bit seed from &lt;code&gt;crypto.getRandomValues&lt;/code&gt;, the same way the server seeds it. Where an exact answer exists I computed it separately, by formula or by listing every possible draw, and checked the simulation against it.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The hat fails about 63% of the time
&lt;/h3&gt;

&lt;p&gt;Put everyone's name in a hat, let everyone pull one. The chance that at least one person pulls their own name:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;People&lt;/th&gt;
&lt;th&gt;Someone draws their own name&lt;/th&gt;
&lt;th&gt;Average full draws until a clean one&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;66.7%&lt;/td&gt;
&lt;td&gt;3.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;62.5%&lt;/td&gt;
&lt;td&gt;2.67&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;63.3%&lt;/td&gt;
&lt;td&gt;2.73&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;63.2%&lt;/td&gt;
&lt;td&gt;2.72&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;63.2%&lt;/td&gt;
&lt;td&gt;2.72&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;63.2%&lt;/td&gt;
&lt;td&gt;2.72&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;From 6 people up the number stops moving. A draw where nobody gets themselves is a &lt;em&gt;derangement&lt;/em&gt;, and the share of shuffles that are derangements converges to 1/e (36.8%) almost immediately, so the failure rate sits at 1 − 1/e and the expected number of full draws sits at e, about 2.72.&lt;/p&gt;

&lt;p&gt;As a sanity check I shuffled 8 names 1,000,000 times with a plain Fisher–Yates shuffle. 632,287 shuffles had at least one person holding their own name: 63.23%, against an exact 63.21%.&lt;/p&gt;

&lt;p&gt;I keep a version of this table, along with what to do when it happens, on the &lt;a href="https://secretsantagenerator.xyz/secret-santa-rules/" rel="noopener noreferrer"&gt;Secret Santa rules page&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. "Just redraw that one person" is worse than it sounds
&lt;/h3&gt;

&lt;p&gt;The usual fix at the table: if you pull your own name, put it back and draw again. Two things go wrong.&lt;/p&gt;

&lt;p&gt;First, the last person can be left holding only their own slip. Second, even when it works, the pairings are no longer equally likely. People who draw early pick freely, people who draw late get what's left, so some complete pairings can be reached in many ways and others in very few.&lt;/p&gt;

&lt;p&gt;I computed both exactly by walking every possible sequence of draws:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;People&lt;/th&gt;
&lt;th&gt;Last person stuck with their own name&lt;/th&gt;
&lt;th&gt;Most likely pairing vs least likely&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;13.9%&lt;/td&gt;
&lt;td&gt;3×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;13.2%&lt;/td&gt;
&lt;td&gt;4×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;11.3%&lt;/td&gt;
&lt;td&gt;5×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;9.0%&lt;/td&gt;
&lt;td&gt;7×&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In each case the gap between the most and least likely full outcome was exactly n − 1. Nobody at a party will notice a 5× bias, but it's the kind of thing a generator should not have. The only paper method that stays fair is the boring one: if anyone gets themselves, everyone puts their slip back and you start over.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. What the generator does instead: shuffle, check, start over
&lt;/h3&gt;

&lt;p&gt;That boring method is also the right algorithm. Shuffle uniformly, check every rule, and if anything fails, throw the whole shuffle away. Conditioning a uniform distribution on "the result is valid" gives a uniform distribution over valid results, so no valid draw is favoured.&lt;/p&gt;

&lt;p&gt;A stripped-down version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// allowed(g, r): may g give to r? (g !== r, plus any exclusions)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;drawNames&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rng&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;tries&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;rng&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;       &lt;span class="c1"&gt;// forward Fisher–Yates&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;
      &lt;span class="nx"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;              &lt;span class="c1"&gt;// a[i] is final now, so check it early&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;receivers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tries&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bailing out at the first broken rule is safe because the rejected attempt is discarded whole. The real module also checks up front that a valid draw exists at all (more on that below) and caps the number of attempts, so it can't spin forever.&lt;/p&gt;

&lt;p&gt;Results from &lt;strong&gt;1,000,000 draws of 8 people&lt;/strong&gt; through the real module, no exclusions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average attempts: &lt;strong&gt;2.719&lt;/strong&gt; (exact: 2.718)&lt;/li&gt;
&lt;li&gt;Worst case: 32 attempts&lt;/li&gt;
&lt;li&gt;Time: about 7.5 µs per draw on my laptop&lt;/li&gt;
&lt;li&gt;The slower fallback for very tight rules was never needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Is it actually uniform?&lt;/strong&gt; With 5 people there are exactly 44 valid draws. In 440,000 runs each one should show up about 10,000 times. The rarest came up 9,826 times and the most common 10,204. A chi-square test gives 27.8 on 43 degrees of freedom, p = 0.96: nothing to see. I ran the same test on 6 people with 2 couples kept apart (116 valid draws, 400,000 runs each time) six times: p = 0.04, 0.54, 0.73, 0.96, 0.24 and 0.74. One run in twenty lands under 0.05 by chance with a fair draw, and the reruns of that setup scattered the way they should.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. What exclusions cost
&lt;/h3&gt;

&lt;p&gt;Couples who shouldn't draw each other are the most common rule. Every rule removes valid draws, so the shuffle gets rejected more often:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Group&lt;/th&gt;
&lt;th&gt;Valid draws / all orderings&lt;/th&gt;
&lt;th&gt;Share that pass&lt;/th&gt;
&lt;th&gt;Measured attempts&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;6 people, 3 couples&lt;/td&gt;
&lt;td&gt;80 / 720&lt;/td&gt;
&lt;td&gt;11.1%&lt;/td&gt;
&lt;td&gt;8.97&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8 people, 2 couples&lt;/td&gt;
&lt;td&gt;8,132 / 40,320&lt;/td&gt;
&lt;td&gt;20.2%&lt;/td&gt;
&lt;td&gt;4.98&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8 people, 4 couples&lt;/td&gt;
&lt;td&gt;4,752 / 40,320&lt;/td&gt;
&lt;td&gt;11.8%&lt;/td&gt;
&lt;td&gt;8.46&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10 people, 5 couples&lt;/td&gt;
&lt;td&gt;440,192 / 3,628,800&lt;/td&gt;
&lt;td&gt;12.1%&lt;/td&gt;
&lt;td&gt;8.24 (exact)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12 people, 6 couples&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;8.06&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;200 people, 100 couples&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;7.58&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For a computer, 8 attempts is nothing; the 200-person case took about 5 ms per draw, most of it the up-front feasibility check. For a group doing it by hand with slips, "everyone puts their slip back" nine times in a row is where the evening goes. This is the case the &lt;a href="https://secretsantagenerator.xyz/secret-santa-generator-with-exclusions/" rel="noopener noreferrer"&gt;generator with exclusions&lt;/a&gt; exists for.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Households and the "half" limit
&lt;/h3&gt;

&lt;p&gt;Families usually want more than couples apart: everyone under one roof. That has a hard limit, and it's a textbook result. A draw exists only if every group of givers has at least as many allowed recipients as it has members (Hall's condition). A household of k people needs k recipients outside the house, so a household can be at most half the group.&lt;/p&gt;

&lt;p&gt;Exact counts for 10 people with one household kept apart:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Household size&lt;/th&gt;
&lt;th&gt;Valid draws (of 3,628,800 orderings)&lt;/th&gt;
&lt;th&gt;Expected attempts&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;585,900 (16.1%)&lt;/td&gt;
&lt;td&gt;6.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;181,440 (5.0%)&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;14,400 (0.4%)&lt;/td&gt;
&lt;td&gt;252 (measured: 252.2)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;impossible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;At exactly half, the draw is forced into two teams: every household member buys for someone outside and every outsider buys for someone inside, 5! × 5! = 14,400 ways. Rejection sampling still copes at 252 attempts. One more person in the household and there's no valid draw, so instead of looping the module returns the blocking group: in my 6-of-10 test, five household members who between them could only give to four people. I go through the family version of this, with several households and kids, on the &lt;a href="https://secretsantagenerator.xyz/family-secret-santa/" rel="noopener noreferrer"&gt;family Secret Santa page&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Mutual pairs, and why there's a "one big circle" switch
&lt;/h3&gt;

&lt;p&gt;A uniformly random valid draw often contains two people who buy for each other. That's legal, but some groups find it flat:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;People&lt;/th&gt;
&lt;th&gt;At least one mutual pair&lt;/th&gt;
&lt;th&gt;Draw is one single loop&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;33.3%&lt;/td&gt;
&lt;td&gt;66.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;39.6%&lt;/td&gt;
&lt;td&gt;45.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;39.4%&lt;/td&gt;
&lt;td&gt;34.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;39.4%&lt;/td&gt;
&lt;td&gt;22.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;39.4%&lt;/td&gt;
&lt;td&gt;13.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The million-draw run agreed: 39.42% of the 8-person draws had a mutual pair and 33.96% formed one loop.&lt;/p&gt;

&lt;p&gt;If you want a single chain (A gives to B, B to C, and the last person back to A), the generator has a one-big-circle mode that uses Sattolo's algorithm instead of Fisher–Yates. It's the backward Fisher–Yates loop with one small change, &lt;code&gt;j = rng.int(i)&lt;/code&gt; instead of &lt;code&gt;rng.int(i + 1)&lt;/code&gt;, and it produces every single loop with equal probability. No mutual pairs and no separate loops by construction; with no exclusions it always passes on the first attempt, and with 4 couples among 8 people it took 3.39 attempts on average. The chain is handy when the reveal happens on a call: each person opens their gift, says who they had, and that person goes next. I wrote up how that works for remote teams on the &lt;a href="https://secretsantagenerator.xyz/virtual-secret-santa/" rel="noopener noreferrer"&gt;virtual Secret Santa page&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Two smaller things that turned out to matter
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Seeds make draws auditable.&lt;/strong&gt; Every draw stores its 128-bit seed and runs it through a small PRNG (sfc32). Same seed and same inputs give the same result, so if someone says "the draw was rigged", it can be replayed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tight rules need a fallback, but a labelled one.&lt;/strong&gt; If rejection sampling hasn't found a valid draw within its budget, the module switches to a randomized search plus random swaps that keep every rule. That's only approximately uniform, so the result records which method produced it. In all the runs above it never triggered.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The short version
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A paper hat draw fails about 63% of the time for any group of 6 or more.&lt;/li&gt;
&lt;li&gt;Redrawing only the unlucky person can strand the last drawer (9 to 14% of the time in groups of 4 to 8) and makes some pairings up to n − 1 times likelier than others. Restart from scratch instead.&lt;/li&gt;
&lt;li&gt;Couples cost you roughly 5 to 9 full draws. Fine for code, painful with slips.&lt;/li&gt;
&lt;li&gt;No household can be more than half the group.&lt;/li&gt;
&lt;li&gt;In groups of 6 or more, about 39% of random draws contain a mutual pair; a single-loop draw avoids that.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;I built secretsantagenerator.xyz. An AI agent working for me ran these simulations on the generator's draw code and wrote this post from the results, with no line-by-line human edit, so it's marked as AI-generated. The exact counts don't depend on randomness; the simulated figures should land within a fraction of a percent if you rerun them.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>algorithms</category>
      <category>math</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I retested my AI image checker on GPT Image 2.5, Nano Banana 2.1, FLUX.3 and Midjourney V7</title>
      <dc:creator>Han Lou</dc:creator>
      <pubDate>Thu, 29 Oct 2026 02:20:44 +0000</pubDate>
      <link>https://dev.to/han_lou_493c3fecccc66c1f0/i-retested-my-ai-image-checker-on-gpt-image-25-nano-banana-21-flux3-and-midjourney-v7-5do9</link>
      <guid>https://dev.to/han_lou_493c3fecccc66c1f0/i-retested-my-ai-image-checker-on-gpt-image-25-nano-banana-21-flux3-and-midjourney-v7-5do9</guid>
      <description>&lt;p&gt;Two weeks ago I ran 100 images through four AI image detectors to pick the engine behind a small checker I built. Since then OpenAI shipped GPT Image 2.5 (September 8) and Google shipped Nano Banana 2.1 (October 6). A detector that was fine on last season's models can fall behind quickly, so I retested the checker as it actually runs today on the newest generators I could get clean samples from.&lt;/p&gt;

&lt;p&gt;The question was narrow: &lt;strong&gt;how often does an image from a new generator come back as anything other than "Likely AI-generated", and how often is a real camera photo flagged?&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Rules first, results second
&lt;/h3&gt;

&lt;p&gt;I wrote the protocol down before the first detection call: which images, how they're picked, how answers are counted, and what I'd change on the site depending on the result. The one decision rule: if any generator is missed more than 1 time in 5, results that come back "Likely a real photo" or "Can't tell" get a short note saying how many images from that generator we missed.&lt;/p&gt;

&lt;p&gt;A miss means anything other than "Likely AI-generated". The checker has three answers: Likely AI (detection score 0.8 or above), Likely a real photo (0.2 or below) and Can't tell (in between). So a Can't tell on an AI image counts against it.&lt;/p&gt;

&lt;p&gt;No threshold tuning, no swapping out images after seeing a score. Spares were allowed only for download or format failures, and they were fixed before any score existed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where the images came from
&lt;/h3&gt;

&lt;p&gt;Provenance was the hard part. A file called "midjourney.png" on the internet proves nothing, so each bucket needed a source that records the model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GPT Image 2.5, Nano Banana (2.1, 2, 2 Lite, Pro), FLUX.3 and Flux.2 [dev]:&lt;/strong&gt; made with Civitai's on-site generator, which writes down the model it called. Text-to-image only, no source image, no LoRAs, at most one image per user. 20 per family.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Midjourney V7:&lt;/strong&gt; original PNG downloads from a CC0 archive on Hugging Face whose embedded prompt carries &lt;code&gt;--v 7&lt;/code&gt; and a Midjourney job id. 20 images, but all from one creator, so they share a style.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Midjourney, recent community posts:&lt;/strong&gt; 20 r/midjourney showcase posts. Reddit strips the prompt, so the version can't be verified. I report this row separately and never pool it with the others.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real photos:&lt;/strong&gt; 40 camera originals from Wikimedia Commons "Taken with …" categories, shot in 2024 or later: 24 from recent phones (iPhone 17 Pro, 16 Pro, Pixel 10 Pro, Galaxy S25 Ultra and others) and 16 from mirrorless cameras.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's 140 images. I kept links and fingerprints, not the images.&lt;/p&gt;

&lt;h3&gt;
  
  
  Two findings before any model ran
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;None of the 60 Civitai files carried Content Credentials.&lt;/strong&gt; That includes the 20 GPT Image 2.5 images. In my first test, all 8 original OpenAI files carried OpenAI-signed credentials (6 I made through OpenAI's image API, 2 from a public dataset), and the checker settled them without calling a model. Files that come out of a third-party generator site don't necessarily keep them, so here the detection model had to decide. If you're trying to work out whether ChatGPT made a particular picture, I wrote up &lt;a href="https://aiimagedetection.app/chatgpt-image-detector/" rel="noopener noreferrer"&gt;when OpenAI's credentials settle it and when they don't&lt;/a&gt;, and &lt;a href="https://aiimagedetection.app/openai-image-verification/" rel="noopener noreferrer"&gt;what OpenAI's own verifier can and can't confirm&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Labels anyone can write were common.&lt;/strong&gt; 6 of the 20 Nano Banana files and all 20 Midjourney V7 files carried an AI label in their metadata. The checker doesn't trust that kind of label on its own, because anyone can add it to a real photo, so those images still went to the model. Only signed credentials from signers on the C2PA trust lists settle an answer: in this run that happened for 3 real photos, which carried Google Pixel camera credentials. For a single picture, the order the checker works through (signed credentials, then metadata, then the model, with your own eyes last) is written up on an &lt;a href="https://aiimagedetection.app/is-this-image-ai-generated/" rel="noopener noreferrer"&gt;is this image AI-generated&lt;/a&gt; page.&lt;/p&gt;

&lt;p&gt;A small product bug turned up as well: two 4K PNGs from Civitai were over the site's 25 MB upload limit. On the live site those uploads fail with "too large".&lt;/p&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;p&gt;Run on October 28, 2026, through the same code path the site uses, with Sightengine as the detection model.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Generator&lt;/th&gt;
&lt;th&gt;Images&lt;/th&gt;
&lt;th&gt;Likely AI&lt;/th&gt;
&lt;th&gt;Can't tell&lt;/th&gt;
&lt;th&gt;Called a real photo&lt;/th&gt;
&lt;th&gt;Missed (95% range)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI GPT Image 2.5&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0 of 20 (0–16%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Nano Banana 2.1, 2 and Pro&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0 of 20 (0–16%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FLUX.3 and Flux.2 [dev]&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1 of 20 (1–24%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Midjourney V7&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1 of 20 (1–24%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Midjourney, community posts (version not verified)&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2 of 20 (3–30%)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;78 of the 80 verified AI images came back Likely AI and none were called a real photo. Every miss in the main rows was a Can't tell: a Flux.2 [dev] image scored 0.79, just under the 0.8 cut-off, and a Midjourney V7 image scored 0.55. In the community row, one post scored 0.77 (Can't tell) and one scored 0.06, the only AI image in the run the checker called a real photo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real photos:&lt;/strong&gt; 38 of 40 came back Likely a real photo. One was flagged as AI with a score of 0.99, and one got a Can't tell at 0.64. That's 1 of 40 flagged (2.5%, 95% range 0–13%). Both errors were recent iPhone shots, an iPhone 17 and an iPhone 17 Pro. Two photos aren't a pattern, but it's the case I'd watch, because a false alarm lands on a real person. If the image you're checking is a viral picture or a screenshot rather than an original file, the clues are different; I keep &lt;a href="https://aiimagedetection.app/is-this-photo-ai/" rel="noopener noreferrer"&gt;notes on checking those&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;No generator crossed the 1-in-5 line, so the decision rule said no warning, and I didn't add one.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the numbers don't say
&lt;/h3&gt;

&lt;p&gt;Twenty images per generator is small. "0 of 20 missed" is still compatible with missing about 1 in 6, which is what the 95% range shows. The Midjourney V7 images come from a single creator. The community Midjourney row can't be tied to a version. Civitai's generator is one way to reach these models, not the only one, and files from other apps may behave differently, especially around credentials. And vendors update their models, so this is a snapshot of one week.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disclosure
&lt;/h3&gt;

&lt;p&gt;I built this checker and it uses Sightengine as its main engine, with Hive as a backup, so I have a stake in these numbers looking good. That's why the protocol was written first and why every row is published, misses included. No detection company paid for this or saw it in advance.&lt;/p&gt;

&lt;p&gt;The full table, the method and the earlier 100-image comparison of four engines are on the &lt;a href="https://aiimagedetection.app/ai-image-detector-accuracy/" rel="noopener noreferrer"&gt;accuracy page&lt;/a&gt;. If you have an image from one of these generators that it gets wrong, I'd like to see it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;An AI agent working for me wrote this post from the test logs, with no line-by-line human edit, so it's marked as AI-generated. The images, the runs and the numbers are real; the method and the full table are on the accuracy page.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>computervision</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I tested 8 AI song detectors on the same songs. Here's what actually works</title>
      <dc:creator>Han Lou</dc:creator>
      <pubDate>Thu, 22 Oct 2026 04:20:26 +0000</pubDate>
      <link>https://dev.to/han_lou_493c3fecccc66c1f0/i-tested-8-ai-song-detectors-on-the-same-songs-heres-what-actually-works-4lpg</link>
      <guid>https://dev.to/han_lou_493c3fecccc66c1f0/i-tested-8-ai-song-detectors-on-the-same-songs-heres-what-actually-works-4lpg</guid>
      <description>&lt;p&gt;"Is this song AI?" is a question a lot of people now type into a search box, and it's one a chatbot can't answer, because it can't listen to the track. I wanted to build a small checker for it, so first I had to find out which detection engine actually works. Vendor accuracy claims don't say how they were measured, so I ran my own test: 8 detectors on the same songs, and 65 songs in total for the one that came out on top.&lt;/p&gt;

&lt;p&gt;It's a small test with real gaps, and I list them at the end. But the results were lopsided enough to be worth sharing.&lt;/p&gt;

&lt;h3&gt;
  
  
  The test set
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;25 AI songs from 17 acts that the press has identified as AI&lt;/strong&gt;, mostly released in 2025. Among them: The Velvet Sundown, Xania Monet, Breaking Rust, Cain Walker, Sienna Rose, Aventhis, Solomon Ray, King Willonius ("BBL Drizzy") and TaTa ("Pulse", made by Timbaland's team with Suno). The Velvet Sundown is the clearest case, because the band now says so itself: since July 2025 its Spotify bio has called it a synthetic music project made with the support of AI. The timeline and our scores are on &lt;a href="https://isthissongai.app/is-the-velvet-sundown-ai/" rel="noopener noreferrer"&gt;Is The Velvet Sundown AI?&lt;/a&gt;. Country, gospel and soul show up a lot, because that's where many of the AI acts in the news are. On the gospel side, Apple Music describes Solomon Ray as an AI entity made by rapper Christopher Townsend; the charts it reached are on &lt;a href="https://isthissongai.app/is-solomon-ray-ai/" rel="noopener noreferrer"&gt;Is Solomon Ray AI?&lt;/a&gt;. The full list of acts, who identified each one as AI and how every song scored is on my &lt;a href="https://isthissongai.app/ai-artists/" rel="noopener noreferrer"&gt;AI artists page&lt;/a&gt;. One act that isn't in this test set: Eddie Dalton, the blues persona whose album &lt;em&gt;The Years Between&lt;/em&gt; went to No. 1 on Billboard's Blues Albums chart; Newsweek reported it was made with AI. The reporting and our scores are on &lt;a href="https://isthissongai.app/is-eddie-dalton-ai/" rel="noopener noreferrer"&gt;Is Eddie Dalton AI?&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;40 human songs, picked to be hard.&lt;/strong&gt; I didn't want an easy pass from acoustic ballads, so the set includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;heavy Auto-Tune and vocoders: Cher's "Believe", T-Pain, Bon Iver's "715 - CRΣΣKS"&lt;/li&gt;
&lt;li&gt;electronic production: Daft Punk, Skrillex, Radiohead's "Everything In Its Right Place"&lt;/li&gt;
&lt;li&gt;country, soul and gospel in the same styles as the AI songs: Chris Stapleton, Zach Bryan, Leon Bridges, Kirk Franklin, CeCe Winans&lt;/li&gt;
&lt;li&gt;recent hits a model can't have memorised for long: "Espresso", "Not Like Us", "DtMF", "The Fate of Ophelia"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Audio:&lt;/strong&gt; the official 30-second preview from Apple Music (AAC 256 kbps). That's what a checker can legally fetch when someone pastes a link, so that's what I tested on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The pass line was fixed before I ran anything:&lt;/strong&gt; at least 80% correct, and no more than 10% of human songs flagged as AI, on a core set of 40 songs (20 AI, 20 human). If no engine passed, I wasn't going to launch. Later I added 25 more songs (5 AI, 20 human) to narrow the error range on false alarms.&lt;/p&gt;

&lt;h3&gt;
  
  
  The results
&lt;/h3&gt;

&lt;p&gt;All engines on the same 40 core songs, each with a simple 0.5 cut-off:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Engine&lt;/th&gt;
&lt;th&gt;Correct&lt;/th&gt;
&lt;th&gt;Human songs flagged as AI&lt;/th&gt;
&lt;th&gt;AI songs missed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;fakeprint (open-source, runs locally)&lt;/td&gt;
&lt;td&gt;95%&lt;/td&gt;
&lt;td&gt;0 of 20&lt;/td&gt;
&lt;td&gt;2 of 20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deezer's album AI label (35 songs found on Deezer)&lt;/td&gt;
&lt;td&gt;94%&lt;/td&gt;
&lt;td&gt;0 of 18&lt;/td&gt;
&lt;td&gt;2 of 17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fakeprint CNN (second model, same project)&lt;/td&gt;
&lt;td&gt;92.5%&lt;/td&gt;
&lt;td&gt;2 of 20&lt;/td&gt;
&lt;td&gt;1 of 20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini 4 Argon, asked to listen (35 usable replies)&lt;/td&gt;
&lt;td&gt;88.6%&lt;/td&gt;
&lt;td&gt;3 of 19&lt;/td&gt;
&lt;td&gt;1 of 16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini 3.8 Flash, asked to listen&lt;/td&gt;
&lt;td&gt;82.5%&lt;/td&gt;
&lt;td&gt;1 of 20&lt;/td&gt;
&lt;td&gt;6 of 20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hive, general AI-generated audio detection&lt;/td&gt;
&lt;td&gt;62.5%&lt;/td&gt;
&lt;td&gt;0 of 20&lt;/td&gt;
&lt;td&gt;15 of 20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SONICS 5-second model (ICLR 2025)&lt;/td&gt;
&lt;td&gt;57.5%&lt;/td&gt;
&lt;td&gt;1 of 20&lt;/td&gt;
&lt;td&gt;16 of 20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SONICS 120-second model&lt;/td&gt;
&lt;td&gt;50%&lt;/td&gt;
&lt;td&gt;20 of 20&lt;/td&gt;
&lt;td&gt;0 of 20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;AI or Not would have been number nine, but its music model returned HTTP 403 on the free plan, so it isn't in the table.&lt;/p&gt;

&lt;p&gt;A few notes so nobody over-reads this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;These are 30-second previews of 40 songs, not product reviews.&lt;/strong&gt; For Hive I could only reach its general AI-audio and deepfake endpoint, not its music-specific model, so the 62.5% doesn't rate that product.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The SONICS 120-second model expects far more audio than a preview gives it.&lt;/strong&gt; Feeding it the 30-second clip tiled to length helped (65%, but 9 of 20 human songs flagged). It's a research model trained on Suno and Udio songs from its own dataset, and it shows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Gemini numbers are flattering on the human side.&lt;/strong&gt; Both models recognise famous songs, so "this is human" on Queen or Eminem may just be memory. Even so, they flagged human songs: Gemini 3.8 Flash called Eminem's "Lose Yourself" AI, and Gemini 4 Argon flagged "Lose Yourself", "Bohemian Rhapsody" and Holding Absence's "Afterlife". Argon also returned unusable replies on 5 of the 40.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The fakeprint CNN flagged Billie Eilish's "bad guy" and "Bohemian Rhapsody".&lt;/strong&gt; Strong on AI songs, but that's two famous human songs called AI out of 20.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I ran the winner on all 65 songs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;fakeprint, all 65 songs&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Correct&lt;/td&gt;
&lt;td&gt;63 of 65 (96.9%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human songs flagged as AI&lt;/td&gt;
&lt;td&gt;0 of 40 (95% interval 0–8.8%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI songs caught&lt;/td&gt;
&lt;td&gt;23 of 25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adding Deezer's album label ("either says AI")&lt;/td&gt;
&lt;td&gt;64 of 65; still 0 of 40 human songs flagged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Highest score on a human song&lt;/td&gt;
&lt;td&gt;0.0007&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lowest score on a caught AI song&lt;/td&gt;
&lt;td&gt;0.873&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That last pair is the part I find most convincing. The scores don't sit near the line. Human songs, including the Auto-Tune and vocoder tracks, were all below 0.001; the caught AI songs were all above 0.87.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why I care more about false alarms than accuracy
&lt;/h3&gt;

&lt;p&gt;"Accuracy" mixes two very different mistakes, and they don't cost the same.&lt;/p&gt;

&lt;p&gt;A missed AI song is a shame. A human song called AI lands on a person: a singer who gets accused in the comments, an indie artist whose track gets pulled from a playlist, a label that has to defend a release. If most songs people check turn out to be human, which seems likely, even a small false-alarm rate does real damage.&lt;/p&gt;

&lt;p&gt;Here's the arithmetic with made-up but plausible numbers. Say 1 in 10 songs people check is really AI, and a detector catches 95% of AI songs but also flags 10% of human ones. Out of 1,000 checks it makes 95 correct "AI" calls and 90 wrong ones. Nearly half of its "AI" answers would be accusations against real musicians, even though its headline accuracy looks fine.&lt;/p&gt;

&lt;p&gt;Two more things worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero isn't zero.&lt;/strong&gt; 0 of 40 human songs flagged is a good result from a small test, but with only 40 songs the 95% interval still runs up to about 8.8%. Treat any "likely AI" verdict as one piece of evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Give the detector a way to say "I don't know".&lt;/strong&gt; The checker I built answers "Likely AI-generated" at 0.8 or above, "Likely human-made" at 0.2 or below, and "Can't tell" in between. None of the 65 Apple previews landed in the middle, but some re-encoded copies did, which is exactly what that middle band is for.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Does compression break it?
&lt;/h3&gt;

&lt;p&gt;I re-encoded every preview three ways and also scored Deezer's own MP3 previews:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Copy&lt;/th&gt;
&lt;th&gt;AI songs called "Likely AI"&lt;/th&gt;
&lt;th&gt;Human songs called "Likely human"&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Apple preview (AAC 256k), the main test&lt;/td&gt;
&lt;td&gt;23 of 25&lt;/td&gt;
&lt;td&gt;40 of 40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Re-encoded to MP3 128 kbps&lt;/td&gt;
&lt;td&gt;21 of 25&lt;/td&gt;
&lt;td&gt;40 of 40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Re-encoded to Opus 64 kbps&lt;/td&gt;
&lt;td&gt;20 of 25&lt;/td&gt;
&lt;td&gt;40 of 40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Downsampled to 22 kHz, then AAC 96 kbps&lt;/td&gt;
&lt;td&gt;19 of 25&lt;/td&gt;
&lt;td&gt;40 of 40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deezer's MP3 128k previews (58 songs found there)&lt;/td&gt;
&lt;td&gt;18 of 22&lt;/td&gt;
&lt;td&gt;36 of 36&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Heavy compression costs some AI catches; those songs mostly slid into "Can't tell". But no human song moved towards AI in any version, so the model is reacting to the generator, not to the codec. One odd case: Breaking Rust's "Livin' On Borrowed Time" scored 0.998 on Apple's preview and 0.0006 on Deezer's. I don't know why; Deezer may carry a different master. That's why the checker fetches Apple's preview first. Billboard calls Breaking Rust an AI-powered country act, and its "Walk My Walk" topped Country Digital Song Sales; the sources and our test scores are on &lt;a href="https://isthissongai.app/is-breaking-rust-ai/" rel="noopener noreferrer"&gt;Is Breaking Rust AI?&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How the fingerprint works (and one porting trap)
&lt;/h3&gt;

&lt;p&gt;AI music generators build a song as a compressed code and then turn it into sound with a neural audio decoder. The decoder's upsampling layers leave a row of evenly spaced peaks in the spectrum, roughly between 1 and 8 kHz. You can't hear it, but you can measure it. Researchers at Deezer described this in a 2025 ISMIR paper (Afchar et al., "A Fourier Explanation of AI-music Artifacts").&lt;/p&gt;

&lt;p&gt;The open-source fakeprint model (lofcz/ai-music-detector, MIT licence) turns that into a tiny detector: resample to 16 kHz, take an 8192-point FFT, average the spectrum over the clip, subtract its lower envelope so the music's own shape drops out, and feed the remaining peaks to a 15 KB logistic regression. In my runs it took about a tenth of a second per song and cost nothing.&lt;/p&gt;

&lt;p&gt;The trap if you port it: &lt;strong&gt;the resampler has to match training&lt;/strong&gt;, which used torchaudio's default sinc filter. A different resampling filter can create spectral peaks of its own, and then you're measuring your resampler instead of the generator. The model's author ships alignment tests for exactly this. I ported it to run in the browser, so the first pass on an uploaded file happens on the device, and checked the port against the Python scores on all 65 songs: the largest difference was under 0.0005, and no verdict changed.&lt;/p&gt;

&lt;h3&gt;
  
  
  What this test can't tell you
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;New generators can slip past it.&lt;/strong&gt; The model card covers Suno up to v5 and Udio up to v1.5. Suno released v6 on September 9, 2026, after these songs were made, and I haven't tested it, or ElevenLabs Music, Google Lyria or Mureka. Expect misses until it's retested.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part-AI songs usually pass as human.&lt;/strong&gt; TaTa's "Pulse" uses an AI voice with human production and scored below 0.001. Hive, both Gemini models and Deezer's label missed it too. The check answers "was this whole track generated?", not "was AI used anywhere?".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The licensing has a grey area.&lt;/strong&gt; The model's code and weights are MIT, but its training data includes the SONICS dataset, licensed CC BY-NC 4.0 for research, plus data the author doesn't publish. Deezer has also filed patent applications on AI-detection methods; I haven't checked whether they cover this one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's small and I picked it.&lt;/strong&gt; 25 AI songs, all from acts named in the press and mostly from 2025, and 40 human songs I chose. A different set could score differently, and the range on the AI miss rate is still wide (2.2–25%).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deezer's label comes from an undocumented interface&lt;/strong&gt; that can change, and it only applies to whole albums. I also looked at it while choosing AI songs, so its AI-side result isn't blind. Its human-side result (0 of 36 flagged) is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I'm not neutral.&lt;/strong&gt; I built a checker on top of fakeprint and Deezer's label, so I have an interest in good numbers. No vendor paid for this or saw it first. Hive ran on free trial credit and Gemini through OpenRouter at standard prices (about $0.003 per check).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  If you want to check one song
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Look at who's behind it.&lt;/strong&gt; An artist with no live shows, no interviews and a burst of releases in a few months is a reason to look closer, not proof.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the platform's own labels.&lt;/strong&gt; Deezer tags albums its detector found to be AI; it's worth a look if the song is there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run a detector as one more clue,&lt;/strong&gt; preferably one that shows its score, its reasons, and is allowed to say "can't tell".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't use a detector's answer alone to accuse a real musician.&lt;/strong&gt; Not mine, not anyone's.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A longer version of this list, nine clues with how much each one tells you (Spotify's AI Persona badge and AI credits included), is on &lt;a href="https://isthissongai.app/how-to-tell-if-a-song-is-ai/" rel="noopener noreferrer"&gt;How to tell if a song is AI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I put this into a small free checker: paste a Spotify, Apple Music, YouTube or Deezer link, or upload a file. The first pass runs in your browser; for the deeper check a short excerpt (30 to 60 seconds) is sent to the server and then discarded, and no audio is stored. It's at &lt;a href="https://isthissongai.app/" rel="noopener noreferrer"&gt;isthissongai.app&lt;/a&gt; (1 free check a day, no sign-up). Every song, every score, the re-encoding results and the full list of limits are on the &lt;a href="https://isthissongai.app/accuracy/" rel="noopener noreferrer"&gt;accuracy page&lt;/a&gt;. If it gets one of your songs wrong, I'd really like to hear about it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt; &lt;a href="https://arxiv.org/abs/2506.19108" rel="noopener noreferrer"&gt;Afchar et al., A Fourier Explanation of AI-music Artifacts, ISMIR 2025&lt;/a&gt;; &lt;a href="https://huggingface.co/lofcz/ai-music-detector" rel="noopener noreferrer"&gt;lofcz/ai-music-detector model card&lt;/a&gt;; &lt;a href="https://huggingface.co/datasets/awsaf49/sonics" rel="noopener noreferrer"&gt;SONICS dataset&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I used an AI assistant to help draft and edit this post. The test set, the runs and the numbers are from my own test, published in full on the accuracy page.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>ai</category>
      <category>music</category>
      <category>webdev</category>
    </item>
    <item>
      <title>AI画像判定ツール4つを100枚で検証してわかった、正解率より大事なこと</title>
      <dc:creator>Han Lou</dc:creator>
      <pubDate>Wed, 21 Oct 2026 13:57:20 +0000</pubDate>
      <link>https://dev.to/han_lou_493c3fecccc66c1f0/aihua-xiang-pan-ding-turu4tuwo100mei-dejian-zheng-sitewakatuta-zheng-jie-lu-yorida-shi-nakoto-3n2o</link>
      <guid>https://dev.to/han_lou_493c3fecccc66c1f0/aihua-xiang-pan-ding-turu4tuwo100mei-dejian-zheng-sitewakatuta-zheng-jie-lu-yorida-shi-nakoto-3n2o</guid>
      <description>&lt;p&gt;X で拡散している画像や、LINE で回ってきたスクショを見て「これ、生成AIで作ったものでは？」と思ったことがある人は多いと思います。AI画像の判定ツールはいくつもあり、どのサービスも正解率をうたっています。ただ、その数字をどう測ったのかはどこにも書かれていないので、比べようがありません。&lt;/p&gt;

&lt;p&gt;私はいま小さなAI画像判定ツールを作っていて、裏側で使う検出エンジンを選ぶ必要がありました。そこで自分でテストしてみました。規模は小さく、抜けもあります（後でまとめて書きます）。それでも、この種のツールに対する見方はかなり変わりました。&lt;/p&gt;

&lt;h3&gt;
  
  
  テストに使った画像
&lt;/h3&gt;

&lt;p&gt;100枚。すべて2026年10月13日に実行しました。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;本物の写真50枚。&lt;/strong&gt; 大半は Wikimedia Commons の CC0 またはクリエイティブ・コモンズ・ライセンスの画像です。うち38枚は元ファイルで、スマホのスナップ、ポートレート、風景、商品写真です。50枚中37枚は EXIF にカメラの機種名が残っていて、iPhone、Pixel、Galaxy のものでした。残りの12枚は、「出回った写真」に見えるように私が作ったコピーです。スマホ風のスクショ4枚、チャットアプリでよくあるように強く再圧縮したもの4枚、軽くレタッチしたもの4枚です。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI画像50枚。&lt;/strong&gt; 6つの画像生成AIのシリーズから集めました。OpenAI GPT Image、Google Nano Banana、Black Forest Labs FLUX.2、Midjourney（v6〜v8.1）、ByteDance Seedream、Stable Diffusion XL です。42枚は2025年以降に公開された生成AIによるものです。AIの元ファイル40枚のうち、27枚はこのテストのために自分で生成し（API料金は約1.42ドル）、13枚は Hugging Face 上のオープンライセンスのデータセットから取りました。最後の10枚はAI画像をスマホ風にスクショしたもので、PNG で保存し、メタデータは一切ありません。&lt;/p&gt;

&lt;h3&gt;
  
  
  採点のしかた
&lt;/h3&gt;

&lt;p&gt;すべてのエンジンに同じファイルを渡しました。回答はエンジンごとに決めた固定のルールで「AI」か「本物」に変換しています。Sightengine はスコア0.5以上、Hive は公式推奨のしきい値0.9、AI or Not と WasItAI は各社自身の判定をそのまま使いました。「不明」という回答は不正解として数えています。&lt;/p&gt;

&lt;p&gt;数字を見る前に一つ注意があります。100枚すべてを見たのは2つのエンジンだけです。無料トライアルの範囲内で済ませたため、AI or Not は層化抽出した20枚、WasItAI は9枚だけで実行しました。&lt;/p&gt;

&lt;h3&gt;
  
  
  結果
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;エンジン&lt;/th&gt;
&lt;th&gt;テスト枚数&lt;/th&gt;
&lt;th&gt;正解率&lt;/th&gt;
&lt;th&gt;本物の写真をAIと誤判定&lt;/th&gt;
&lt;th&gt;検出できたAI画像&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sightengine&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;99%&lt;/td&gt;
&lt;td&gt;50枚中0枚&lt;/td&gt;
&lt;td&gt;50枚中49枚&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hive&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;95%&lt;/td&gt;
&lt;td&gt;50枚中0枚&lt;/td&gt;
&lt;td&gt;50枚中45枚&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI or Not&lt;/td&gt;
&lt;td&gt;20（サンプル）&lt;/td&gt;
&lt;td&gt;85%&lt;/td&gt;
&lt;td&gt;10枚中1枚&lt;/td&gt;
&lt;td&gt;10枚中8枚&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WasItAI&lt;/td&gt;
&lt;td&gt;9（サンプル）&lt;/td&gt;
&lt;td&gt;78%&lt;/td&gt;
&lt;td&gt;5枚中2枚&lt;/td&gt;
&lt;td&gt;4枚中4枚&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;下の2行はランキングとして読まないでください。20枚と9枚では少なすぎます。AI or Not のサンプルは全体より難しく、スクショや再圧縮したコピーの割合が高めでした。唯一の誤判定も、軽くレタッチした写真です。4つのエンジンすべてが見た9枚に限ると、Sightengine と Hive は9枚中9枚、AI or Not は9枚中8枚、WasItAI は9枚中7枚が正解でした。目安にはなりますが、結論ではありません。&lt;/p&gt;

&lt;p&gt;生成AI別に見ると、いちばん難しかったのは FLUX です。Sightengine は FLUX の画像9枚中8枚、Hive は9枚中6枚を検出しました。Midjourney の画像は、両エンジンとも全部検出しています。&lt;/p&gt;

&lt;h3&gt;
  
  
  正解率より誤判定を見る理由
&lt;/h3&gt;

&lt;p&gt;「正解率」には、性質のまったく違う2種類の間違いが混ざっています。私のテスト用プログラムには、どんな画像にも「AI」と答える偽のエンジンがあります（配線の確認にだけ使うものです）。このテストセットでは、それでもAI画像50枚を全部当てて、正解率は50%になります。本物の写真50枚もすべてAIと判定しているからです。&lt;/p&gt;

&lt;p&gt;この2つの間違いは、重さが違います。AI画像を見逃すのは残念なことです。でも本物の写真をAIと言われると、その被害は実在の人に向かいます。フリマアプリで本当に不良品が届いて返金を求めた購入者、線を一本一本自分で描いたイラストレーター、マッチングアプリでただ写真がうまいだけの人。チェックする画像の大半が実は本物なら、誤判定率が小さくても、正しい指摘より間違った疑いのほうが多くなりえます。&lt;/p&gt;

&lt;p&gt;ほかにも、予想していなかったことが2つあります。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;しきい値は「選択」です。&lt;/strong&gt; Hive の推奨値0.9では、本物の写真の誤判定はゼロで、AI画像の90%を検出しました。0.5にすれば96%を検出できますが、本物の写真50枚中1枚を誤判定します。こうしたエンジンを使った製品は、どれもこの曲線上のどこかを選んでいて、たいていそれを教えてくれません。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ゼロは「ゼロ」ではありません。&lt;/strong&gt; Sightengine と Hive はどちらも、本物の写真50枚中0枚の誤判定でした。ただ50枚しかないので、95%信頼区間は0%から約7%まであります。小さなテストとしては良い兆候ですが、保証ではありません。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  コンテンツクレデンシャル：多くの人が飛ばしている無料のチェック
&lt;/h3&gt;

&lt;p&gt;いくつかのAIツールは、生成したファイルに C2PA という標準規格で署名するようになりました。一般にはコンテンツクレデンシャル（Content Credentials）と呼ばれています。記録にはどのツールで作ったかが書かれていて、暗号技術でファイルと結びついています。読み取りは無料で、ブラウザ上でもできます。&lt;/p&gt;

&lt;p&gt;今回のセットでは、AI画像50枚中24枚にコンテンツクレデンシャルが付いていて、本物の写真には「AI生成」という記載のあるものは一枚もありませんでした。署名元は OpenAI、Google、Black Forest Labs、BytePlus（ByteDance）です。24枚はすべて元ファイルで、AIの元ファイル40枚のうち24枚に付いていたことになります。&lt;/p&gt;

&lt;p&gt;後になってから本気で気にするようになった落とし穴が一つあります。署名が有効だとわかるのは「誰が署名したか」であって、「その署名者を信用してよいか」ではありません。24枚のうち、C2PA の公式信頼リストに載っている企業（OpenAI と Google）が署名していたのは14枚だけでした。残りの10枚は、リストにない証明書で署名されていました。自分で作った証明書なら、何にでも署名できます。そのため私のツールでは、この10枚と、Midjourney のような単なるメタデータのラベルは「自己申告」として扱い、検出モデルも実行しています。&lt;/p&gt;

&lt;p&gt;注意点をまとめます。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Midjourney のファイルには一度も付いていませんでした&lt;/strong&gt;（元ファイル7枚中0枚）。Stable Diffusion XL も同じです（5枚中0枚）。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;スクショにすると消えます。&lt;/strong&gt; 10枚のスクショには一枚も付いていませんでした。スクショはまったく新しいファイルなので、署名は引き継がれません。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;私のファイルの一部は、それ以前に失っていたかもしれません。&lt;/strong&gt; 公開データセットから取ったものがいくつかあり、保存し直したコピーでは記録が落ちることがあります。数が少ないからといって、その生成AIが署名しないとは言い切れません。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;カメラも署名します。&lt;/strong&gt; Google Pixel 9 と Pixel 10 で撮った本物の写真2枚には、カメラのクレデンシャルが付いていました。クレデンシャルが本物の写真をAIと示したことは一度もありません。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;つまり、コンテンツクレデンシャルは、あればほぼ証拠になり、なくても何もわかりません。X で拡散している画像をスクショで見かけたなら、見つからないものと思っておいたほうがいいでしょう。&lt;/p&gt;

&lt;p&gt;上の表は、エンジン同士を比べるために単純な固定の線（Sightengine なら0.5）で判定しています。ツール自体はもっと慎重で、0.8を超えたらAI、0.2未満なら本物、その間は「判定できません」と答えます。クレデンシャルを先に読み、残りだけを Sightengine に送って、この2本の線で判定した結果は、100枚中98枚が正解、1枚が「判定できません」（本物の写真のスクショで、スコア0.21）、1枚が誤り（FLUX のスクショで、スコア0.18、本物と判定）でした。本物の写真の誤判定は、やはり50枚中0枚です。16枚は信頼できるクレデンシャルだけで決着し、モデルを呼ぶ必要がありませんでした（AI画像14枚と、本物の撮影として署名された Pixel の写真2枚）。残りの84枚がモデルに回りました。&lt;/p&gt;

&lt;p&gt;スクショは、モデルにとっても少し不利です。AIの元画像とそのスクショのペア10組で比べると、Sightengine は検出数が10から9に、Hive は10から8に下がりました。&lt;/p&gt;

&lt;h3&gt;
  
  
  第3の答え：「AIで編集済み」
&lt;/h3&gt;

&lt;p&gt;テストセットを作っている途中、ある Pixel の写真のメタデータに「Edited with Google AI」と書かれていました。完全な本物でも、完全な生成画像でもないので、本物の写真のグループからは外して差し替えました。主要な2エンジンはどちらも本物と判定していて、それはそれで妥当です。ただ、多くのスマホ写真にとって「本物かAIか」という問い自体がずれてきていることがわかります。役に立つ判定ツールには、3つ目の答えが必要です。&lt;/p&gt;

&lt;h3&gt;
  
  
  このテストでわからないこと
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;規模が小さいです。100枚、1日だけです。&lt;/li&gt;
&lt;li&gt;4つのエンジンのうち2つは、サンプルしか見ていません。&lt;/li&gt;
&lt;li&gt;マッチングアプリの自撮り、強いフィルターをかけたポートレート、手描きの作品、合成画像や部分的なAI編集は入っていません。イラストも数枚だけです。&lt;/li&gt;
&lt;li&gt;本物の写真1枚だけは、1日の無料枠がリセットされた後、ほかより数時間遅れて Sightengine と Hive にかけました。&lt;/li&gt;
&lt;li&gt;各社はモデルを更新するので、これはある時点のスナップショットです。&lt;/li&gt;
&lt;li&gt;私は中立ではありません。私が作ったツールはいま Sightengine を使い、Hive を予備にしています。どの事業者もこのテストにお金を出しておらず、事前に内容を見てもいません。4つとも無料トライアルのクレジットで実行しました。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1枚の画像を確かめるなら
&lt;/h3&gt;

&lt;p&gt;ある1枚の画像について知りたいだけなら、私はこの順番で確かめます。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;コンテンツクレデンシャルを探す。&lt;/strong&gt; Content Authenticity Initiative の無料ツール Verify（contentcredentials.org/verify）で読み取れます。画像生成AIの名前が出れば、ほぼそこで終わりです。何も出なくても次へ進んでください。それが普通です。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;いちばん古いコピーを探す。&lt;/strong&gt; Google レンズ、TinEye、Bing で画像検索（逆画像検索）をします。その画像が最初に出てきた場所から、誰がなぜ作ったのかがわかることがよくあります。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;場面のつじつまが合っているかを考える。&lt;/strong&gt; 制服は合っているか、道路標識は合っているか、天気はその日付と合っているか。このチェックは、生成AIが進歩しても弱くなりません。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;それから細部を見る。&lt;/strong&gt; 小さな文字、物を持つ手、映り込み、影、人混みの中で繰り返される顔。これらは手がかりにすぎません。おかしな細部が一つあってもAIの証明にはならず、完璧な画像だからといってカメラで撮った証明にもなりません。見分け方のコツは「&lt;a href="https://aiimagedetection.app/ja/ai-gazou-miwakekata/" rel="noopener noreferrer"&gt;AI画像の見分け方&lt;/a&gt;」にもまとめています。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;判定ツールは手がかりの一つとして使う。&lt;/strong&gt; スコアの幅と理由を示してくれて、「判定できません」と言えるものを選ぶのがおすすめです。できれば元のファイルを使ってください。スクショは判定が難しくなります。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;何がわかったとしても、判定ツールの答えだけを根拠に、実在の人を責めないでください。&lt;/p&gt;

&lt;p&gt;このクレデンシャル優先の流れを、無料の小さなツール「&lt;a href="https://aiimagedetection.app/ja/" rel="noopener noreferrer"&gt;AI画像判定&lt;/a&gt;」にしました。テストの方法の全体、生成AIごとの数字、限界は&lt;a href="https://aiimagedetection.app/ai-image-detector-accuracy/" rel="noopener noreferrer"&gt;正確性についてのページ（英語）&lt;/a&gt;に載せています。うまく判定できない画像があれば、ぜひ見せてください。&lt;/p&gt;

&lt;p&gt;この記事の英語版は dev.to に掲載しています：&lt;a href="https://dev.to/han_lou_493c3fecccc66c1f0/i-tested-4-ai-image-detectors-on-100-images-heres-what-id-tell-a-friend-5738"&gt;I tested 4 AI image detectors on 100 images&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;この記事の下書きと編集には AI アシスタントの手を借りました。テストセット、実行、数字はすべて私自身のものです。&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>japanese</category>
      <category>computervision</category>
    </item>
    <item>
      <title>KI-Bild oder echt? Ich habe 4 Detektoren mit 100 Bildern getestet</title>
      <dc:creator>Han Lou</dc:creator>
      <pubDate>Wed, 21 Oct 2026 13:56:09 +0000</pubDate>
      <link>https://dev.to/han_lou_493c3fecccc66c1f0/ki-bild-oder-echt-ich-habe-4-detektoren-mit-100-bildern-getestet-48oc</link>
      <guid>https://dev.to/han_lou_493c3fecccc66c1f0/ki-bild-oder-echt-ich-habe-4-detektoren-mit-100-bildern-getestet-48oc</guid>
      <description>&lt;p&gt;Irgendwann landet so ein Bild im Familienchat: eine WhatsApp-Weiterleitung, schon etwas verpixelt, und darunter die Frage „Ist das echt?“. KI-Detektoren gibt es inzwischen reichlich, und jeder Anbieter wirbt mit einer Trefferquote. Wie die gemessen wurde, schreibt keiner dazu. Vergleichen lassen sich die Zahlen also nicht.&lt;/p&gt;

&lt;p&gt;Ich baue gerade einen kleinen KI-Bild-Checker und musste mich irgendwann für die Erkennungs-Engine dahinter entscheiden. Also habe ich selbst getestet. Der Test ist klein und hat Lücken (die liste ich unten auf), aber er hat verändert, wie ich über diese Tools denke.&lt;/p&gt;

&lt;h3&gt;
  
  
  Die Testbilder
&lt;/h3&gt;

&lt;p&gt;100 Bilder, alle am 13. Oktober 2026 durchgelaufen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;50 echte Fotos&lt;/strong&gt;, größtenteils von Wikimedia Commons unter CC0- oder Creative-Commons-Lizenz. 38 davon sind Originaldateien: Handyfotos, Porträts, Landschaften, Produktfotos. Bei 37 der 50 stand noch ein Kameramodell in den EXIF-Daten, von iPhone-, Pixel- und Galaxy-Handys. Die übrigen 12 sind Kopien, die ich so aufbereitet habe, dass sie wie herumgereichte Fotos aussehen: 4 Screenshots im Handy-Stil, 4 stark nachkomprimierte Kopien, wie Messenger sie erzeugen, und 4 leicht retuschierte Versionen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;50 KI-Bilder&lt;/strong&gt; aus sechs Generator-Familien: OpenAI GPT Image, Google Nano Banana, Black Forest Labs FLUX.2, Midjourney (v6 bis v8.1), ByteDance Seedream und Stable Diffusion XL. 42 stammen von Generatoren, die 2025 oder später erschienen sind. Von den 40 KI-Originaldateien habe ich 27 extra für diesen Test erzeugt (rund 1,42 US-Dollar an API-Kosten), 13 stammen aus offen lizenzierten Datensätzen auf Hugging Face. Die letzten 10 sind Screenshots von KI-Bildern im Handy-Stil, als PNG gespeichert, ganz ohne Metadaten.&lt;/p&gt;

&lt;h3&gt;
  
  
  So habe ich gewertet
&lt;/h3&gt;

&lt;p&gt;Jede Engine bekam dieselben Dateien. Jede Antwort habe ich mit einer festen Regel pro Engine in „KI“ oder „echt“ übersetzt: bei Sightengine ein Score ab 0,5, bei Hive der vom Anbieter selbst empfohlene Schwellenwert von 0,9, bei AI or Not und WasItAI das Urteil des Anbieters. Ein „unbekannt“ zählte als falsch.&lt;/p&gt;

&lt;p&gt;Eine Einschränkung vorab: Nur zwei Engines haben alle 100 Bilder gesehen. Ich bin innerhalb der kostenlosen Testkontingente geblieben, deshalb lief AI or Not nur auf einer geschichteten Stichprobe von 20 Bildern und WasItAI auf 9.&lt;/p&gt;

&lt;h3&gt;
  
  
  Die Ergebnisse
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Engine&lt;/th&gt;
&lt;th&gt;Getestete Bilder&lt;/th&gt;
&lt;th&gt;Genauigkeit&lt;/th&gt;
&lt;th&gt;Echte Fotos als KI markiert&lt;/th&gt;
&lt;th&gt;Erkannte KI-Bilder&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sightengine&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;99 %&lt;/td&gt;
&lt;td&gt;0 von 50&lt;/td&gt;
&lt;td&gt;49 von 50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hive&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;95 %&lt;/td&gt;
&lt;td&gt;0 von 50&lt;/td&gt;
&lt;td&gt;45 von 50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI or Not&lt;/td&gt;
&lt;td&gt;20 (Stichprobe)&lt;/td&gt;
&lt;td&gt;85 %&lt;/td&gt;
&lt;td&gt;1 von 10&lt;/td&gt;
&lt;td&gt;8 von 10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WasItAI&lt;/td&gt;
&lt;td&gt;9 (Stichprobe)&lt;/td&gt;
&lt;td&gt;78 %&lt;/td&gt;
&lt;td&gt;2 von 5&lt;/td&gt;
&lt;td&gt;4 von 4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Bitte lies die unteren beiden Zeilen nicht als Rangliste. 20 und 9 Bilder sind zu wenig. Die Stichprobe von AI or Not war außerdem schwerer als der Gesamtsatz, mit mehr Screenshots und nachkomprimierten Kopien, und ihr einziger Fehlalarm war ein leicht retuschiertes Foto. Bei den 9 Bildern, die alle vier Engines gesehen haben, kamen Sightengine und Hive auf 9 von 9, AI or Not auf 8 von 9 und WasItAI auf 7 von 9. Ein Hinweis, kein Urteil.&lt;/p&gt;

&lt;p&gt;Nach Generator war FLUX am schwierigsten: Sightengine erkannte 8 von 9 FLUX-Bildern, Hive 6 von 9. Jedes Midjourney-Bild haben beide Engines erkannt.&lt;/p&gt;

&lt;h3&gt;
  
  
  Warum mich Fehlalarme mehr interessieren als die Genauigkeit
&lt;/h3&gt;

&lt;p&gt;„Genauigkeit“ wirft zwei sehr unterschiedliche Fehler in einen Topf. In meinem Test-Setup gibt es eine Fake-Engine, die bei jedem Bild „KI“ sagt; die nutze ich nur, um die Pipeline durchzutesten. Auf diesem Testsatz erkennt sie alle 50 KI-Bilder und kommt trotzdem auf 50 % Genauigkeit, weil sie eben auch alle 50 echten Fotos markiert.&lt;/p&gt;

&lt;p&gt;Die beiden Fehler kosten nicht dasselbe. Ein übersehenes KI-Bild ist schade. Ein echtes Foto, das als KI abgestempelt wird, trifft einen Menschen: die Käuferin, die zu Recht ihr Geld zurückverlangt, den Zeichner, der jeden Strich selbst gesetzt hat, jemanden in einer Dating-App, der einfach gute Fotos macht. Wenn die meisten Bilder, die du prüfst, am Ende echt sind, kann schon eine kleine Fehlalarmquote mehr falsche Beschuldigungen produzieren als richtige.&lt;/p&gt;

&lt;p&gt;Zwei Dinge, mit denen ich nicht gerechnet hatte:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Der Schwellenwert ist eine Entscheidung.&lt;/strong&gt; Mit dem von Hive empfohlenen Schwellenwert von 0,9 wurde kein echtes Foto markiert, und 90 % der KI-Bilder wurden erkannt. Bei 0,5 wären es 96 % gewesen, dafür aber 1 von 50 echten Fotos als Fehlalarm. Jedes Produkt, das auf diesen Engines aufsetzt, wählt einen Punkt auf dieser Kurve, meistens ohne es dir zu sagen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Null ist nicht null.&lt;/strong&gt; Sightengine und Hive haben beide 0 von 50 echten Fotos markiert. Bei nur 50 Fotos reicht das 95-%-Konfidenzintervall trotzdem von 0 % bis etwa 7 %. Ein gutes Zeichen aus einem kleinen Test, keine Garantie.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Content Credentials: der kostenlose Check, den die meisten auslassen
&lt;/h3&gt;

&lt;p&gt;Manche KI-Tools signieren ihre Dateien inzwischen nach dem C2PA-Standard, öffentlich bekannt als Content Credentials. Der Eintrag nennt das Tool und ist kryptografisch an die Datei gebunden. Ihn auszulesen kostet nichts und geht direkt im Browser.&lt;/p&gt;

&lt;p&gt;In meinem Testsatz trugen 24 der 50 KI-Bilder Content Credentials, und kein einziges echtes Foto trug eine KI-Angabe. Als Unterzeichner tauchten OpenAI, Google, Black Forest Labs und BytePlus (ByteDance) auf. Alle 24 waren Originaldateien: 24 der 40 KI-Originale hatten Credentials.&lt;/p&gt;

&lt;p&gt;Einen Haken habe ich erst später ernst genommen: Eine gültige Signatur sagt dir, wer unterschrieben hat, nicht, ob du dem trauen solltest. Nur 14 der 24 waren von Firmen signiert, die auf der offiziellen C2PA-Vertrauensliste stehen (OpenAI und Google). Die anderen 10 waren mit Zertifikaten signiert, die dort nicht stehen, und ein selbst ausgestelltes Zertifikat kann alles signieren. Mein Checker behandelt diese 10, genauso wie reine Metadaten-Labels wie das von Midjourney, deshalb nur als Behauptung und lässt trotzdem das Erkennungsmodell laufen.&lt;/p&gt;

&lt;p&gt;Die Haken im Einzelnen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Midjourney-Dateien hatten nie welche&lt;/strong&gt; (0 von 7 Originalen), Stable Diffusion XL ebenfalls nicht (0 von 5).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Screenshots verlieren sie.&lt;/strong&gt; Keiner der 10 Screenshots trug Credentials. Ein Screenshot ist eine komplett neue Datei, die Signatur kommt nicht mit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manche meiner Dateien haben sie vielleicht schon vorher verloren.&lt;/strong&gt; Einige stammen aus öffentlichen Datensätzen, und eine neu gespeicherte Kopie kann den Eintrag verlieren. Eine niedrige Zahl beweist also nicht, dass ein Generator nie signiert.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auch Kameras signieren.&lt;/strong&gt; Zwei echte Fotos, von einem Google Pixel 9 und einem Pixel 10, trugen Kamera-Credentials, und Credentials haben nie ein echtes Foto als KI markiert.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Heißt: Wenn Content Credentials da sind, sind sie fast ein Beweis. Fehlen sie, sagt das gar nichts. Wenn dich ein virales Bild als Screenshot erreicht, rechne damit, keine zu finden.&lt;/p&gt;

&lt;p&gt;Die Tabelle oben nutzt eine einfache feste Grenze (bei Sightengine 0,5), damit sich die Engines vergleichen lassen. Das Tool selbst ist vorsichtiger: Es nennt ein Bild über 0,8 KI, unter 0,2 echt und sagt dazwischen „kann ich nicht sagen“. Credentials zuerst lesen, nur den Rest an Sightengine schicken, mit diesen beiden Grenzen: 98 von 100 richtig, 1 „kann ich nicht sagen“ (ein Screenshot eines echten Fotos mit Score 0,21), 1 falsch (ein FLUX-Screenshot mit 0,18, als echt eingestuft), und weiterhin 0 von 50 echten Fotos markiert. 16 Bilder waren allein über vertrauenswürdige Credentials geklärt, ganz ohne Modellaufruf (14 KI-Bilder plus 2 Pixel-Fotos, die als echte Aufnahmen signiert waren). Die anderen 84 gingen ans Modell.&lt;/p&gt;

&lt;p&gt;Screenshots kosten auch die Modelle etwas. Bei 10 Paaren aus KI-Original und dazugehörigem Screenshot fiel Sightengine von 10 erkannten auf 9, Hive von 10 auf 8.&lt;/p&gt;

&lt;h3&gt;
  
  
  Eine dritte Antwort: „mit KI bearbeitet“
&lt;/h3&gt;

&lt;p&gt;Beim Zusammenstellen hatte ein Pixel-Foto in den Metadaten den Vermerk „Edited with Google AI“. Es ist weder ganz echt noch ganz generiert, also habe ich es aus den echten Fotos herausgenommen und ersetzt. Beide Haupt-Engines hatten es als echt eingestuft, was fair ist. Es zeigt aber, dass „echt oder KI“ für viele Handyfotos zunehmend die falsche Frage ist. Ein brauchbarer Checker braucht eine dritte Antwort.&lt;/p&gt;

&lt;h3&gt;
  
  
  Was dieser Test nicht leisten kann
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Er ist klein: 100 Bilder, ein Tag.&lt;/li&gt;
&lt;li&gt;Zwei der vier Engines haben nur Stichproben gesehen.&lt;/li&gt;
&lt;li&gt;Es fehlen Dating-App-Selfies, stark gefilterte Porträts, handgemachte Kunst sowie Composings oder teilweise mit KI bearbeitete Bilder. Illustrationen sind nur wenige dabei.&lt;/li&gt;
&lt;li&gt;Ein echtes Foto lief ein paar Stunden nach den anderen durch Sightengine und Hive, nachdem sich deren tägliche Gratis-Kontingente zurückgesetzt hatten.&lt;/li&gt;
&lt;li&gt;Anbieter aktualisieren ihre Modelle, das hier ist eine Momentaufnahme.&lt;/li&gt;
&lt;li&gt;Ich bin nicht neutral. Mein Checker nutzt inzwischen Sightengine, mit Hive als Backup. Kein Anbieter hat für den Test bezahlt oder ihn vorab gesehen, und alle vier liefen über kostenlose Testguthaben.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  So würde ich ein einzelnes Bild prüfen
&lt;/h3&gt;

&lt;p&gt;Wenn du nur wissen willst, was mit einem bestimmten Bild los ist, würde ich in dieser Reihenfolge vorgehen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Nach Content Credentials schauen.&lt;/strong&gt; Das kostenlose Verify-Tool der Content Authenticity Initiative (contentcredentials.org/verify) liest sie aus. Nennt es einen KI-Generator, bist du im Grunde fertig. Zeigt es nichts an, mach weiter; das ist normal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Die früheste Kopie finden.&lt;/strong&gt; Mach eine Bilder-Rückwärtssuche mit Google Lens, TinEye oder Bing. Wo ein Bild zuerst aufgetaucht ist, verrät oft, wer es gemacht hat und warum.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fragen, ob die Szene stimmt.&lt;/strong&gt; Passen die Uniformen, die Verkehrsschilder, das Wetter zum Datum? Dieser Check wird nicht schwächer, wenn die Generatoren besser werden.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dann genau hinschauen.&lt;/strong&gt; Kleine Schrift, Hände, die etwas halten, Spiegelungen, Schatten, sich wiederholende Gesichter in einer Menschenmenge. Das sind Indizien: Ein seltsames Detail beweist keine KI, und ein makelloses Bild beweist keine Kamera. Worauf man im Detail achten kann, habe ich unter &lt;a href="https://aiimagedetection.app/de/woran-erkennt-man-ki-bilder/" rel="noopener noreferrer"&gt;Woran erkennt man KI-Bilder?&lt;/a&gt; gesammelt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Einen Detektor als weiteres Indiz nutzen.&lt;/strong&gt; Am besten einen, der eine Spanne und seine Gründe zeigt und auch „kann ich nicht sagen“ antworten darf. Nimm wenn möglich die Originaldatei, Screenshots sind schwerer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Egal, was du findest: Beschuldige keinen echten Menschen allein aufgrund der Antwort eines Detektors.&lt;/p&gt;

&lt;p&gt;Diesen Ablauf mit Credentials zuerst habe ich in einen kleinen kostenlosen Checker gepackt: &lt;a href="https://aiimagedetection.app/de/" rel="noopener noreferrer"&gt;KI-Bild erkennen&lt;/a&gt;. Die vollständige Methode, alle Zahlen nach Generator und die Grenzen des Tests stehen auf der &lt;a href="https://aiimagedetection.app/ai-image-detector-accuracy/" rel="noopener noreferrer"&gt;Seite zur Genauigkeit (auf Englisch)&lt;/a&gt;. Wenn du ein Bild hast, bei dem er danebenliegt, würde ich es gern sehen.&lt;/p&gt;

&lt;p&gt;Die englische Originalfassung ist auf dev.to erschienen: &lt;a href="https://dev.to/han_lou_493c3fecccc66c1f0/i-tested-4-ai-image-detectors-on-100-images-heres-what-id-tell-a-friend-5738"&gt;I tested 4 AI image detectors on 100 images&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Beim Entwerfen und Redigieren dieses Beitrags hat mir ein KI-Assistent geholfen. Die Testbilder, die Durchläufe und die Zahlen sind meine eigenen.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>german</category>
      <category>deutsch</category>
    </item>
    <item>
      <title>實測 4 款 AI 圖片偵測工具（100 張圖）：比準確率更該看的是誤判</title>
      <dc:creator>Han Lou</dc:creator>
      <pubDate>Wed, 21 Oct 2026 13:47:34 +0000</pubDate>
      <link>https://dev.to/han_lou_493c3fecccc66c1f0/shi-ce-4-kuan-ai-tu-pian-zhen-ce-gong-ju-100-zhang-tu-bi-zhun-que-lu-geng-gai-kan-de-shi-wu-pan-23h7</link>
      <guid>https://dev.to/han_lou_493c3fecccc66c1f0/shi-ce-4-kuan-ai-tu-pian-zhen-ce-gong-ju-100-zhang-tu-bi-zhun-que-lu-geng-gai-kan-de-shi-wu-pan-23h7</guid>
      <description>&lt;p&gt;LINE 群組裡又轉來一張截圖，可能是某個名人「推薦」投資群組的廣告，可能是哪裡淹水的現場照片，你想知道它是不是 AI 做的。上網一查，AI 圖片偵測工具一大堆，每家都寫著自己的準確率有多高，卻沒有一家說清楚是怎麼量出來的，根本沒辦法比。&lt;/p&gt;

&lt;p&gt;我最近在做一個小小的 AI 圖片檢查工具，總得替它選一個偵測引擎。既然各家的數字沒辦法比，我就自己測。規模不大，也有不少缺口（後面會一條條列出來），但測完之後，我看這類工具的方式整個變了。&lt;/p&gt;

&lt;h3&gt;
  
  
  測試用的圖
&lt;/h3&gt;

&lt;p&gt;100 張圖，全部在 2026 年 10 月 13 日跑完。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;真實照片 50 張&lt;/strong&gt;，大多來自 Wikimedia Commons，授權是 CC0 或創用 CC。其中 38 張是原始檔：手機隨手拍、人像、風景、商品照。50 張裡有 37 張的 EXIF 還留著相機型號，來自 iPhone、Pixel 和 Galaxy 手機。另外 12 張是我刻意做出來、模仿「被轉傳過」的副本：4 張手機風格的螢幕截圖、4 張像聊天軟體那樣重度壓縮過的檔案、4 張輕度修圖的版本。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI 圖片 50 張&lt;/strong&gt;，來自六個生成器系列：OpenAI GPT Image、Google Nano Banana、Black Forest Labs FLUX.2、Midjourney（v6 到 v8.1）、ByteDance（字節跳動）Seedream 和 Stable Diffusion XL。其中 42 張出自 2025 年以後推出的生成器。40 個 AI 原始檔裡，27 張是我為這次測試自己生成的（API 費用大約 1.42 美元），13 張取自 Hugging Face 上開放授權的資料集。最後 10 張是 AI 圖的手機風格截圖，存成 PNG，完全沒有中繼資料。&lt;/p&gt;

&lt;h3&gt;
  
  
  怎麼計分
&lt;/h3&gt;

&lt;p&gt;每個引擎拿到的檔案完全一樣。每家的回答，我都用一條固定規則轉成「AI」或「真實」：Sightengine 分數 0.5 以上算 AI；Hive 用官方建議的門檻 0.9；AI or Not 和 WasItAI 直接採用廠商自己的判定。回答「不確定」一律算錯。&lt;/p&gt;

&lt;p&gt;看數字之前先講一個前提：只有兩個引擎看過全部 100 張。我只用免費試用額度，所以 AI or Not 只跑了分層抽樣的 20 張，WasItAI 只跑了 9 張。&lt;/p&gt;

&lt;h3&gt;
  
  
  結果
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;引擎&lt;/th&gt;
&lt;th&gt;測試張數&lt;/th&gt;
&lt;th&gt;準確率&lt;/th&gt;
&lt;th&gt;真實照片被判成 AI&lt;/th&gt;
&lt;th&gt;抓到的 AI 圖&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sightengine&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;99%&lt;/td&gt;
&lt;td&gt;0/50&lt;/td&gt;
&lt;td&gt;49/50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hive&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;95%&lt;/td&gt;
&lt;td&gt;0/50&lt;/td&gt;
&lt;td&gt;45/50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI or Not&lt;/td&gt;
&lt;td&gt;20（抽樣）&lt;/td&gt;
&lt;td&gt;85%&lt;/td&gt;
&lt;td&gt;1/10&lt;/td&gt;
&lt;td&gt;8/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WasItAI&lt;/td&gt;
&lt;td&gt;9（抽樣）&lt;/td&gt;
&lt;td&gt;78%&lt;/td&gt;
&lt;td&gt;2/5&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;下面兩列請不要當成排名。20 張和 9 張實在太少。AI or Not 那份樣本也比整體難，截圖和重新壓縮的比例比較高，它唯一一次誤判是一張輕度修圖的照片。四個引擎都看過的那 9 張裡，Sightengine 和 Hive 都是 9 張全對，AI or Not 對 8 張，WasItAI 對 7 張。這只能當參考，不是定論。&lt;/p&gt;

&lt;p&gt;按生成器來看，FLUX 最難抓：Sightengine 9 張抓出 8 張，Hive 9 張抓出 6 張。Midjourney 的圖，兩個引擎都全部抓到。&lt;/p&gt;

&lt;h3&gt;
  
  
  為什麼我比較在意誤判，而不是準確率
&lt;/h3&gt;

&lt;p&gt;「準確率」把兩種性質很不一樣的錯混在一起。我的測試程式裡有一個假引擎，不管什麼圖都回答「AI」，只用來確認整套流程有接通。在這組圖上，它 50 張 AI 圖全部抓到，準確率還是有 50%，因為它也把 50 張真實照片全部判成 AI。&lt;/p&gt;

&lt;p&gt;這兩種錯的代價不一樣。漏掉一張 AI 圖，可惜而已。把真照片說成 AI，倒楣的是一個真實的人：網拍真的收到瑕疵品、申請退款的買家；一筆一筆自己畫出來的繪師；在交友軟體上只是很會拍照的人。如果你檢查的圖大多數其實是真的，就算誤判率很低，冤枉的人也可能比真正抓到的還多。&lt;/p&gt;

&lt;p&gt;還有兩件我沒料到的事：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;門檻是一種選擇。&lt;/strong&gt; 用 Hive 建議的 0.9，它沒有誤判任何一張真實照片，抓到 90% 的 AI 圖。如果改成 0.5，可以抓到 96%，但 50 張真實照片會誤判 1 張。每個用這些引擎做出來的產品，都在這條曲線上選了一個點，通常不會告訴你選在哪裡。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;零誤判不等於真的零。&lt;/strong&gt; Sightengine 和 Hive 都是 50 張真照 0 誤判。但只有 50 張，95% 信賴區間仍然從 0% 到大約 7%。這是小規模測試裡的好兆頭，不是保證。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  內容憑證：大多數人跳過的免費檢查
&lt;/h3&gt;

&lt;p&gt;現在有些 AI 工具會用 C2PA 標準替產出的檔案加上數位簽章，一般叫做「內容憑證」（Content Credentials）。紀錄裡寫著是哪個工具做的，而且用密碼學跟檔案綁在一起。讀它不用錢，在瀏覽器裡就能讀。&lt;/p&gt;

&lt;p&gt;在我的測試組裡，50 張 AI 圖有 24 張帶著內容憑證，真實照片沒有任何一張帶著「AI 生成」的聲明。我看到的簽署者有 OpenAI、Google、Black Forest Labs 和 BytePlus（字節跳動）。這 24 張全部是原始檔，也就是 40 個 AI 原始檔裡有 24 個帶憑證。&lt;/p&gt;

&lt;p&gt;有個重點我後來才認真看待：簽章有效，只告訴你是誰簽的，不代表你該信任它。24 張裡，只有 14 張的簽署者在 C2PA 官方信任清單上（OpenAI 和 Google）。另外 10 張用的數位憑證不在清單上，而自己做的憑證什麼都能簽。所以我的工具把這 10 張，還有像 Midjourney 那種單純寫在中繼資料裡的標籤，都只當成「聲明」，照樣跑偵測模型。&lt;/p&gt;

&lt;p&gt;要注意的地方：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Midjourney 的檔案從來沒有&lt;/strong&gt;（7 個原始檔 0 個），Stable Diffusion XL 也沒有（5 個 0 個）。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;截圖會把它弄丟。&lt;/strong&gt; 10 張截圖沒有一張帶憑證。截圖是一個全新的檔案，簽章不會跟著過去。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;我有些檔案可能早就弄丟了。&lt;/strong&gt; 有幾張來自公開資料集，重新存過的副本可能把紀錄拿掉，所以數量少，不能證明某個生成器從來不簽。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;相機也會簽。&lt;/strong&gt; 兩張真實照片，分別來自 Google Pixel 9 和 Pixel 10，帶著相機的內容憑證；而且內容憑證從來沒有把任何一張真實照片標成 AI。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;所以，有內容憑證的時候，它幾乎就是證據；沒有的時候，什麼也說明不了。如果你在 LINE 群組裡看到的瘋傳圖片是一張截圖，就別期待找得到。&lt;/p&gt;

&lt;p&gt;上面那張表為了方便比較，用的是一條簡單的切線（Sightengine 0.5 以上算 AI）。工具本身比較保守：分數高於 0.8 判 AI，低於 0.2 判真實，中間就說「無法判斷」。先讀內容憑證，剩下的才送 Sightengine，用這兩條線，結果是 100 張中 98 張正確、1 張「無法判斷」（一張真實照片的截圖，分數 0.21）、1 張判錯（一張 FLUX 截圖，分數 0.18，被判成真實），真實照片依然是 0/50 誤判。有 16 張靠可信的內容憑證就有答案，不用呼叫模型（14 張 AI 圖，加上 2 張簽成真實拍攝的 Pixel 照片），其餘 84 張才交給模型。&lt;/p&gt;

&lt;p&gt;截圖也會讓模型掉分。拿 10 組「AI 原圖＋它的截圖」來比，Sightengine 從抓到 10 張掉到 9 張，Hive 從 10 張掉到 8 張。&lt;/p&gt;

&lt;h3&gt;
  
  
  第三種答案：「經 AI 編輯」
&lt;/h3&gt;

&lt;p&gt;整理測試組的時候，有一張 Pixel 照片的中繼資料寫著「Edited with Google AI」。它不算完全真實，也不算完全生成，所以我把它從真實照片裡換掉了。兩個主要引擎都判它是真的，這也說得過去，但這說明了一件事：對很多手機照片來說，「是真的還是 AI」漸漸變成一個問錯的問題。好用的檢查工具需要第三種答案。&lt;/p&gt;

&lt;h3&gt;
  
  
  這個測試沒辦法告訴你的事
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;規模小：100 張圖，一天。&lt;/li&gt;
&lt;li&gt;四個引擎裡有兩個只看了抽樣。&lt;/li&gt;
&lt;li&gt;缺了交友軟體自拍、重度濾鏡人像、手繪作品，也沒有合成圖或局部 AI 修改的圖。插畫只有幾張。&lt;/li&gt;
&lt;li&gt;有一張真實照片比其他圖晚了幾個小時才送進 Sightengine 和 Hive，因為要等它們的每日免費額度重置。&lt;/li&gt;
&lt;li&gt;廠商會更新模型，這只是某一天的快照。&lt;/li&gt;
&lt;li&gt;我不中立。我做的工具現在用 Sightengine，Hive 當備援。沒有任何廠商付錢或事先看過這份測試，四家用的都是免費試用額度。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  如果只想查一張圖
&lt;/h3&gt;

&lt;p&gt;如果你只是想弄清楚某一張圖，我會照這個順序：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;先找內容憑證。&lt;/strong&gt; Content Authenticity Initiative 的免費 Verify 工具（contentcredentials.org/verify）可以讀。如果它寫出某個 AI 生成器，大致就可以確定了。如果什麼都沒有，就往下走，這很正常。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;找最早的版本。&lt;/strong&gt; 用 Google 智慧鏡頭、TinEye 或 Bing 以圖搜圖。一張圖最早出現在哪裡，常常就能看出是誰做的、為什麼做。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;想想畫面合不合理。&lt;/strong&gt; 制服對不對、路牌對不對、天氣跟那天對不對得上。這一關不會因為生成器變強而失效。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;然後再仔細看。&lt;/strong&gt; 小字、手拿東西的地方、倒影、影子、人群裡重複出現的臉。這些都只是線索：一個怪細節不能證明是 AI，一張完美的圖也不能證明是相機拍的。看圖的細節我另外整理在&lt;a href="https://aiimagedetection.app/zh-tw/ruhe-fenbian-ai-tupian/" rel="noopener noreferrer"&gt;如何分辨 AI 圖片&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;把偵測工具當成另一條線索。&lt;/strong&gt; 盡量選會給出分數範圍和理由、而且允許說「無法判斷」的工具。能用原始檔就用原始檔，截圖比較難判。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;不管查到什麼，都不要只憑偵測工具的一個答案就指控一個真實的人。如果那張圖是要你匯款或加入投資群組，與其自己糾結真假，直接打 165 反詐騙諮詢專線問最快。&lt;/p&gt;

&lt;p&gt;我把這套「先讀內容憑證」的流程做成了一個免費小工具：&lt;a href="https://aiimagedetection.app/zh-tw/" rel="noopener noreferrer"&gt;AI 圖片檢測&lt;/a&gt;。完整的方法、每個生成器的數字和測試限制，都寫在&lt;a href="https://aiimagedetection.app/ai-image-detector-accuracy/" rel="noopener noreferrer"&gt;準確度說明頁（英文）&lt;/a&gt;。如果你有它判錯的圖，很歡迎丟給我看看。&lt;/p&gt;

&lt;p&gt;本文的英文原版發表在 dev.to：&lt;a href="https://dev.to/han_lou_493c3fecccc66c1f0/i-tested-4-ai-image-detectors-on-100-images-heres-what-id-tell-a-friend-5738"&gt;I tested 4 AI image detectors on 100 images&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;這篇文章有請 AI 助手協助起草和編輯。測試用的圖、實際執行和所有數字都是我自己的。&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>taiwan</category>
      <category>zh</category>
    </item>
    <item>
      <title>How to run Secret Santa without collecting anyone's email</title>
      <dc:creator>Han Lou</dc:creator>
      <pubDate>Mon, 19 Oct 2026 01:20:38 +0000</pubDate>
      <link>https://dev.to/han_lou_493c3fecccc66c1f0/how-to-run-secret-santa-without-collecting-anyones-email-443</link>
      <guid>https://dev.to/han_lou_493c3fecccc66c1f0/how-to-run-secret-santa-without-collecting-anyones-email-443</guid>
      <description>&lt;p&gt;Most online Secret Santa tools start by asking the organizer for everyone's email address. That's a fair design if you want automatic reminders. But it's a lot to ask at work, where nobody wants another account, and in families, where some relatives barely check email and an invite can land in spam.&lt;/p&gt;

&lt;p&gt;You don't need anyone's email to run a fair draw. Here are three ways to do it, what each is good at, and how to handle the two things that trip groups up: exclusions and remote colleagues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: paper slips, everyone in one room
&lt;/h3&gt;

&lt;p&gt;Write every name on a slip, fold them, and let everyone draw at the same time.&lt;/p&gt;

&lt;p&gt;It's simple and fun, with one known flaw: people pull their own name a lot. With six or more people, there's a 63% chance that at least one person draws their own slip. On average you'll need almost three full draws before one comes out clean.&lt;/p&gt;

&lt;p&gt;The tempting fix is to let that person put the slip back and draw again. Don't. The last person can end up holding only their own name (a 7.6% chance with 10 people, 13.9% with 4), and even when it works, some pairings become more likely than others, up to five times as likely with 6 people. The fair fix is boring: collect every slip and start over.&lt;/p&gt;

&lt;p&gt;Slips also make two things awkward. Keeping a couple apart means redrawing every time they get each other. And everyone has to be in the room.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good for:&lt;/strong&gt; a family dinner or a classroom, small groups, no special rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: a group chat and one trusted helper
&lt;/h3&gt;

&lt;p&gt;Ask someone who isn't taking part, like a partner or a friend outside the group, to draw names and message each person their match privately. A simple way to draw: list the names in a spreadsheet, sort them into a random order, and have each person give to the next one down, with the last person giving to the first.&lt;/p&gt;

&lt;p&gt;This works remotely, and the single circle makes the reveal easy if you open gifts in order. If two partners land next to each other, shuffle again.&lt;/p&gt;

&lt;p&gt;The catch is that the helper knows everything. If the organizer does it, the organizer can't really play. And it all depends on one person sending a dozen private messages without a copy-paste slip.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good for:&lt;/strong&gt; small groups where someone is happy to sit out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 3: an online draw with one private link per person
&lt;/h3&gt;

&lt;p&gt;The online version of "nobody sees the whole list" is a tool that gives each person their own private link instead of emailing them. You send each link the way your group already talks: a direct message, a text, a QR code at the party, or a printed slip for someone without a phone.&lt;/p&gt;

&lt;p&gt;What to look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No accounts for anyone&lt;/strong&gt;, including the organizer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One link per person&lt;/strong&gt;, not one shared link. If everyone uses the same link and types their name to see their match, anyone can type someone else's name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exclusions that work both ways.&lt;/strong&gt; Some tools block "Ana gives to Ben" but still let Ben draw Ana.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;An organizer view that shows who has opened their link but doesn't show who has whom unless the organizer turns on teacher mode, which everyone's page then shows.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A way to add or remove someone after the draw&lt;/strong&gt; without starting over.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic deletion&lt;/strong&gt; after the exchange.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well-known tools like DrawNames and Elfster handle exclusions and wishlists, and they ask for an email address or an account, which is what you trade for reminders. Full disclosure: I built one that follows this checklist, Secret Santa Generator (&lt;a href="https://secretsantagenerator.xyz/secret-santa-generator-with-exclusions/" rel="noopener noreferrer"&gt;https://secretsantagenerator.xyz/secret-santa-generator-with-exclusions/&lt;/a&gt;), but any tool that ticks these boxes will do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good for:&lt;/strong&gt; offices, remote teams, families spread across several households.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting exclusions so the draw stays fair
&lt;/h3&gt;

&lt;p&gt;Exclusions are where well-meaning organizers break their own draw.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Couples and housemates: block both directions.&lt;/strong&gt; If Maya and Leo live together, neither should draw the other.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Last year's pairs: block one direction.&lt;/strong&gt; The point is that Alex doesn't buy for Sam again. Sam can still draw Alex.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep the list short.&lt;/strong&gt; Every rule removes options for everyone. With three couples (six people), only 80 of the 720 possible draws keep every couple apart and nobody drawing themselves. Add last year's pairs and 17 to 20 are left.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Know when it's impossible.&lt;/strong&gt; Three people where two are a couple can't be drawn at all, because both partners would have to give to the third person. A household can be at most half the group: 6 people out of 12 is fine, 7 isn't.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch small groups.&lt;/strong&gt; With two couples there are only 4 valid draws, so everyone can guess their Santa is in the other couple. Add last year's pairs and exactly one draw is left, which means everyone can work out who has whom.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redraw, don't swap.&lt;/strong&gt; If a draw breaks a rule, throw it away and draw again. Swapping two people to patch it makes some pairings more likely than others.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a practical walkthrough, see the &lt;a href="https://secretsantagenerator.xyz/secret-santa-generator-with-exclusions/" rel="noopener noreferrer"&gt;Secret Santa generator with exclusions&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remote and international teams
&lt;/h3&gt;

&lt;p&gt;The draw is the same. Everything after it changes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Addresses:&lt;/strong&gt; don't collect them in a shared spreadsheet. Let each person share their address only with whoever drew them, or ask for something digital instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timing:&lt;/strong&gt; draw names about three weeks before the exchange so people have time to ship; two weeks is enough if everyone is in one office. Set an order-by date at least a week before the call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Borders:&lt;/strong&gt; buying from a store in the recipient's own country avoids international shipping and most customs surprises. Gift cards are often tied to one country and currency, so check before you buy. When the gift ships straight from a store, the card is the only personal part, so I keep &lt;a href="https://secretsantagenerator.xyz/secret-santa-message/" rel="noopener noreferrer"&gt;60 short Secret Santa messages&lt;/a&gt; for coworkers, friends and family.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Budget:&lt;/strong&gt; decide up front whether shipping counts toward the cap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Names:&lt;/strong&gt; colleagues in Australia or Canada may call it Kris Kringle, and in Ireland Kris Kindle. It's the same draw, so use the name the group knows; my &lt;a href="https://secretsantagenerator.xyz/kris-kringle-generator/" rel="noopener noreferrer"&gt;Kris Kringle generator&lt;/a&gt; page is the same tool under that name, with the budget starting in AUD, NZD or EUR from the browser's region.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time zones:&lt;/strong&gt; send a calendar invite rather than typing the time into a message. In 2026, Europe turns its clocks back on October 25 and the US on November 1, so for that week London is 4 hours ahead of New York instead of 5. If your team spans the US, Europe, India and Australia, no single hour works for everyone: run two short calls, or let people unwrap on their own time and share a photo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A quick checklist
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Make it opt-in, and set one budget cap that everyone can afford.&lt;/li&gt;
&lt;li&gt;Pick a draw method: slips, a helper, or private links.&lt;/li&gt;
&lt;li&gt;Add only the exclusions you really need.&lt;/li&gt;
&lt;li&gt;Share each match privately.&lt;/li&gt;
&lt;li&gt;Write down the exchange date, the order-by date and where the reveal happens.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If teenagers are in a family draw, the cap matters more than usual. My list of &lt;a href="https://secretsantagenerator.xyz/secret-santa-gifts-for-teens/" rel="noopener noreferrer"&gt;Secret Santa gifts for teens&lt;/a&gt; has 24 ideas sorted by budget, from under $10 to under $50, mostly things they'd use every day.&lt;/p&gt;

&lt;p&gt;For the announcement itself, I keep &lt;a href="https://secretsantagenerator.xyz/secret-santa-invitation/" rel="noopener noreferrer"&gt;copy-and-paste Secret Santa invitation templates&lt;/a&gt; for a work email, a group chat and a family, with the budget, the dates and an easy opt-out line already in.&lt;/p&gt;

&lt;p&gt;That's all it takes. No email list required.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I used an AI assistant to help draft and edit this post. The test set, the runs and the numbers are my own.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>privacy</category>
    </item>
    <item>
      <title>I tested 4 AI image detectors on 100 images. Here's what I'd tell a friend.</title>
      <dc:creator>Han Lou</dc:creator>
      <pubDate>Thu, 15 Oct 2026 03:30:59 +0000</pubDate>
      <link>https://dev.to/han_lou_493c3fecccc66c1f0/i-tested-4-ai-image-detectors-on-100-images-heres-what-id-tell-a-friend-5738</link>
      <guid>https://dev.to/han_lou_493c3fecccc66c1f0/i-tested-4-ai-image-detectors-on-100-images-heres-what-id-tell-a-friend-5738</guid>
      <description>&lt;p&gt;I've been building a small AI image checker, and at some point I had to pick the detection engine behind it. Every vendor publishes an accuracy figure. None of them says how it was measured, so I couldn't compare them. I ran my own test instead. It's small and it has gaps, which I list below, but it changed how I think about these tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  The test set
&lt;/h3&gt;

&lt;p&gt;100 images, all run on October 13, 2026.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;50 real photos&lt;/strong&gt;, mostly from Wikimedia Commons under CC0 or Creative Commons licenses. 38 are original files: phone shots, portraits, landscapes, product photos. 37 of the 50 still had a camera model in their EXIF, from iPhone, Pixel and Galaxy phones. The other 12 are copies I made to look like photos that have travelled: 4 phone-style screenshots, 4 heavily recompressed copies of the kind chat apps produce, and 4 lightly retouched versions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;50 AI images&lt;/strong&gt; from six generator families: OpenAI GPT Image, Google Nano Banana, Black Forest Labs FLUX.2, Midjourney (v6 to v8.1), ByteDance Seedream and Stable Diffusion XL. 42 come from generators released in 2025 or later. Of the 40 original AI files, I generated 27 for this test (about $1.42 in API calls) and took 13 from openly licensed datasets on Hugging Face. The last 10 are phone-style screenshots of AI images, saved as PNG with no metadata at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I scored it
&lt;/h3&gt;

&lt;p&gt;Every engine got the same files. I turned each answer into "AI" or "real" with one fixed rule per engine: a Sightengine score of 0.5 or higher, Hive's own recommended threshold of 0.9, and the vendor's own verdict for AI or Not and WasItAI. An "unknown" answer counted as wrong.&lt;/p&gt;

&lt;p&gt;One caveat before the numbers: only two engines saw all 100 images. I stayed within free trial allowances, so AI or Not ran on a stratified sample of 20 and WasItAI on 9.&lt;/p&gt;

&lt;h3&gt;
  
  
  The results
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Engine&lt;/th&gt;
&lt;th&gt;Images tested&lt;/th&gt;
&lt;th&gt;Accuracy (one 0.5 cutoff)&lt;/th&gt;
&lt;th&gt;Real photos flagged as AI&lt;/th&gt;
&lt;th&gt;AI images caught&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sightengine&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;99%&lt;/td&gt;
&lt;td&gt;0 of 50&lt;/td&gt;
&lt;td&gt;49 of 50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hive&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;95%&lt;/td&gt;
&lt;td&gt;0 of 50&lt;/td&gt;
&lt;td&gt;45 of 50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI or Not&lt;/td&gt;
&lt;td&gt;20 (sample)&lt;/td&gt;
&lt;td&gt;85%&lt;/td&gt;
&lt;td&gt;1 of 10&lt;/td&gt;
&lt;td&gt;8 of 10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WasItAI&lt;/td&gt;
&lt;td&gt;9 (sample)&lt;/td&gt;
&lt;td&gt;78%&lt;/td&gt;
&lt;td&gt;2 of 5&lt;/td&gt;
&lt;td&gt;4 of 4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Please don't read the bottom two rows as a ranking. Twenty and nine images are too few. AI or Not's sample was also harder than the full set, with a bigger share of screenshots and recompressed copies, and its one false alarm was a lightly retouched photo. On the 9 images that all four engines saw, Sightengine and Hive got 9 of 9, AI or Not 8 of 9 and WasItAI 7 of 9. That's a hint, not a verdict.&lt;/p&gt;

&lt;p&gt;By generator, FLUX was the hardest: Sightengine caught 8 of 9 FLUX images and Hive 6 of 9. Both engines caught every Midjourney image. Stable Diffusion XL was the thinnest bucket: 5 original files from a public dataset plus 1 screenshot, none with Content Credentials or an AI label in the metadata, so I wrote up separately &lt;a href="https://aiimagedetection.app/stable-diffusion-detector/" rel="noopener noreferrer"&gt;what this test does and doesn't say about Stable Diffusion images&lt;/a&gt;. Eleven of the images, AI and real side by side with what each file carried and what fooled the software, are on &lt;a href="https://aiimagedetection.app/ai-vs-real-images/" rel="noopener noreferrer"&gt;AI vs real images&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why I watch false alarms more than accuracy
&lt;/h3&gt;

&lt;p&gt;"Accuracy" mixes two very different mistakes. My test harness has a fake engine that answers "AI" for every image, used only for wiring things up. On this set it catches all 50 AI images and still scores 50% accuracy, because it also flags all 50 real photos.&lt;/p&gt;

&lt;p&gt;The two mistakes don't cost the same. A missed AI image is a shame. A real photo called AI lands on a person: a buyer with a genuine refund claim, an artist who drew every line, someone on a dating app who just takes good photos. If most of the pictures you check turn out to be real, even a small false-alarm rate can produce more wrong accusations than right ones. If you're checking a photo for one of those cases, I wrote separate notes on &lt;a href="https://aiimagedetection.app/ai-generated-damage-photos/" rel="noopener noreferrer"&gt;damage photos in refund claims&lt;/a&gt; and on &lt;a href="https://aiimagedetection.app/ai-photo-detector/" rel="noopener noreferrer"&gt;profile and dating photos&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Two more things I didn't expect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The threshold is a choice.&lt;/strong&gt; At Hive's recommended cutoff of 0.9, it flagged no real photos and caught 90% of the AI images. At 0.5 it would have caught 96%, but flagged 1 real photo in 50. Every product built on these engines picks a point on that curve, usually without telling you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero isn't zero.&lt;/strong&gt; Sightengine and Hive both flagged 0 of 50 real photos. With only 50 photos, the 95% confidence interval still runs from 0% to about 7%. That's a good sign from a small test, not a guarantee.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Content Credentials: the free check most people skip
&lt;/h3&gt;

&lt;p&gt;Some AI tools now sign the files they produce, using the C2PA standard, known publicly as Content Credentials. The record names the tool and is cryptographically tied to the file. Reading it costs nothing and can happen in the browser.&lt;/p&gt;

&lt;p&gt;In my set, 24 of the 50 AI images carried Content Credentials, and none of the real photos carried an AI claim. The signers I saw were OpenAI, Google, Black Forest Labs and BytePlus (ByteDance). All 24 were original files: 24 of the 40 AI originals carried credentials. One catch I only took seriously later: a valid signature tells you who signed, not whether to trust them. Only 14 of those 24 were signed by companies on the official C2PA trust list (OpenAI and Google). The other 10 were signed with certificates that aren't on it, and a self-made certificate can sign anything, so my checker treats those, and plain metadata labels like Midjourney's, as a claim and still runs the detection model.&lt;/p&gt;

&lt;p&gt;The catches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Midjourney files never had them&lt;/strong&gt; (0 of 7 originals), and neither did Stable Diffusion XL (0 of 5).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Screenshots lose them.&lt;/strong&gt; None of the 10 screenshots carried credentials. A screenshot is a brand-new file, so the signature doesn't come along.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Some of my files may have lost them earlier.&lt;/strong&gt; Several came from public datasets, where a re-saved copy can drop the record, so a low count doesn't prove a generator never signs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cameras sign too.&lt;/strong&gt; Two real photos, from a Google Pixel 9 and a Pixel 10, carried camera credentials, and credentials never marked a real photo as AI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So credentials are close to proof when they're there, and their absence tells you nothing. If you meet a viral image as a screenshot, expect to find none. I wrote up &lt;a href="https://aiimagedetection.app/is-this-real-or-ai/" rel="noopener noreferrer"&gt;how I'd check a picture you only saw online&lt;/a&gt;, screenshot or not.&lt;/p&gt;

&lt;p&gt;The table uses one simple cutoff at 0.5 so the engines can be compared. The tool itself is more cautious: it calls an image AI above 0.8, real below 0.2, and says "can't tell" in between. Reading credentials first and sending only the rest to Sightengine, with those two lines, the result was 98 of 100 correct, 1 "can't tell" (a screenshot of a real photo scoring 0.21), 1 wrong (a FLUX screenshot scoring 0.18, called real), and still 0 of 50 real photos flagged. 16 images were settled by trusted credentials without a model call (14 AI images plus 2 Pixel camera photos signed as real captures); the other 84 went to the model.&lt;/p&gt;

&lt;p&gt;Screenshots cost the models a little too. On 10 pairs of an AI original and its screenshot, Sightengine went from 10 caught to 9, and Hive from 10 to 8.&lt;/p&gt;

&lt;h3&gt;
  
  
  A third answer: "edited with AI"
&lt;/h3&gt;

&lt;p&gt;While I was building the set, one Pixel photo's metadata said "Edited with Google AI". It isn't fully real or fully generated, so I swapped it out of the real photos. Both main engines had called it real, which is fair enough, but it shows that "real or AI" is becoming the wrong question for a lot of phone photos. A useful checker needs a third answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  What this test can't tell you
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It's small: 100 images, one day.&lt;/li&gt;
&lt;li&gt;Two of the four engines only saw samples.&lt;/li&gt;
&lt;li&gt;It's missing dating-app selfies, heavily filtered portraits, hand-made artwork, and composites or partial AI edits. There are only a few illustrations.&lt;/li&gt;
&lt;li&gt;One real photo went through Sightengine and Hive a few hours after the rest, once their daily free quotas had reset.&lt;/li&gt;
&lt;li&gt;Vendors update their models, so this is a snapshot.&lt;/li&gt;
&lt;li&gt;I'm not neutral. The checker I built now uses Sightengine, with Hive as a backup. No vendor paid for the test or saw it first, and all four ran on free trial credits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How I'd check a single image
&lt;/h3&gt;

&lt;p&gt;If you just want to know about one picture, this is the order I'd use:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Look for Content Credentials.&lt;/strong&gt; The Content Authenticity Initiative's free Verify tool (contentcredentials.org/verify) reads them. If it names an AI generator, you're mostly done. If it shows nothing, move on; that's normal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find the earliest copy.&lt;/strong&gt; Run a reverse image search with Google Lens, TinEye or Bing. The first place an image appeared often tells you who made it and why.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask whether the scene makes sense.&lt;/strong&gt; The right uniforms, the right road signs, the right weather for the date. This check doesn't get weaker as generators improve.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Then look closely.&lt;/strong&gt; Small text, hands holding things, reflections, shadows, repeated faces in a crowd. Treat these as clues: one odd detail doesn't prove AI, and a flawless picture doesn't prove a camera. The longer version of this step is a &lt;a href="https://aiimagedetection.app/how-to-tell-if-an-image-is-ai-generated/" rel="noopener noreferrer"&gt;visual checklist for telling if an image is AI-generated&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use a detector as one more clue.&lt;/strong&gt; Prefer one that shows a range and its reasons, and that is allowed to say "can't tell". Use the original file if you can, because screenshots are harder.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Whatever you find, don't use a detector's answer alone to accuse a real person.&lt;/p&gt;

&lt;p&gt;I put this credentials-first flow into a small free checker, and the full method, every number by generator and the limits are on its accuracy page: &lt;a href="https://aiimagedetection.app/ai-image-detector-accuracy/" rel="noopener noreferrer"&gt;https://aiimagedetection.app/ai-image-detector-accuracy/&lt;/a&gt;. If you have an image it gets wrong, I'd like to see it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I used an AI assistant to help draft and edit this post. The test set, the runs and the numbers are my own.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>webdev</category>
      <category>privacy</category>
    </item>
  </channel>
</rss>
