<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>_Witrebel</title>
        <link>https://paragraph.com/@witrebel</link>
        <description>undefined</description>
        <lastBuildDate>Sun, 21 Jun 2026 20:22:55 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[Full circle: An AI Generated NFTs struggle to remove its own background]]></title>
            <link>https://paragraph.com/@witrebel/full-circle-an-ai-generated-nfts-struggle-to-remove-its-own-background</link>
            <guid>lRgPeP9peMj5lHT79Nsz</guid>
            <pubDate>Thu, 31 Mar 2022 21:11:31 GMT</pubDate>
            <description><![CDATA[Almost a year ago, Berk created an immersive NFT collection with each image (or BGAN as some call them) generated via a GAN network. This was one of the very first instances of an AI generated NFT. I became intrigued with the project and collected quite a few of them after reading some articles about them and perusing the collection. Most of the BGANs have a solid background, but about 1/5th have a patterned background. An even smaller subset of are actually morphing gifs. There has recently ...]]></description>
            <content:encoded><![CDATA[<p>Almost a year ago, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/berkozdemir">Berk</a> created <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://opensea.io/collection/bastard-gan-punks-v2">an immersive NFT collection</a> with each image (or BGAN as some call them) generated via a GAN network. This was one of the very first instances of an AI generated NFT. I became intrigued with the project and collected quite a few of them after reading some articles about them and perusing the collection. Most of the BGANs have a solid background, but about 1/5th have a patterned background. An even smaller subset of are actually morphing gifs. There has recently been a growing trend to integrate PFP NFT’s [Profile Picture NFT’s] into the metaverse. This integration allows metaverse to participants walk around utilizing their NFT’s as pseudonymous identities. To import an NFT into the metaverse, some platforms require that the API’s for a given collection offer an endpoint that serves the NFT image with the background removed or transparent.</p><p>Now in theory, this would be as easy as asking Berk for the set of original background-less images that the GAN initially produced. The problem was that most of the BGANS were trained with colored backgrounds, so the outputs already had colors merged with the figures, erasing the possibility of separating them easily! Only a set of ~4000 BGANS existed that had no background, but that set wasn&apos;t 100% included in the final published BGAN collection. The community considered manually removing the backgrounds, but at 11305 images, not counting each frame of the Hypes, it was a monumental proposal. There had to be a better way, if only a machine could somehow learn… how to remove a background.</p><p>I did some reading and discovered an open source model called <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/xuebinqin/U-2-Net">U2Net</a>, for salient object detection, was already being employed by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/OPHoperHPO/image-background-remove-tool">some tools</a> for background removal.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e093629c16606194704c9e5e7da5d98608dded00b826fcb4d7a1ac950530d43e.png" alt="Example Results of U2Net Pretrained Background Removal Before" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Example Results of U2Net Pretrained Background Removal Before</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/31e7679b96981b1e322100f8a21081947755708a63f029e08e53e8c8d3b801d0.png" alt="Example Results of U2Net Pretrained Background After" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Example Results of U2Net Pretrained Background After</figcaption></figure><p>Simple! We can just run this tool and it should remove the backgrounds from our BGANs easy peasy right?</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/883b88a1b3ff68949fde776f6473f31254f1dc8c78b96d52d0e68566449bc8ff.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a364b1003dd95a48de54833948cc3426a13de86bc401447c4e9cb5a67f4fcf94.png" alt="U2Net Pretrained Results On BGAN# 764" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">U2Net Pretrained Results On BGAN# 764</figcaption></figure><p>As you can see, the pre-trained model is amazing at real world background removal, but faltered when presented AI-generated pixel art. The challenge was clear. We needed to retrain the U2Net specifically for this type of image. The problem? I have never dabbled in machine learning before, so this was starting from square one.</p><p>The basic concepts seemed manageable, and after some research I laid out a plan.</p><ol><li><p>Develop an algorithm that would locate any matches in the 4600 unlabeled background-less images with their associated BGAN.</p></li><li><p>Use a small set of images that had already had backgrounds manually removed to validate the matching algorithm.</p></li><li><p>Run the algorithm to collect any pairs that exist and label them.</p></li><li><p>Use this data set to retrain the U2Net model</p></li><li><p>Use this new model to automatically remove the backgrounds from the entire collection.</p></li></ol><p>To accomplish the first step of correlating and labeling any pairs that are in our set of background-less images, I employed a Mean Squared Error function. Like always, I jumped straight into the problem when I should have thought things out. I was using 1024x1024 resolution images, and trying to stuff them all into GPU memory using CuPy for MSE analysis. Being somewhat unfamiliar with this field, instead of leveraging frameworks, I basically wrote a very inefficient mechanism to batch load arrays into GPU VRAM. Mostly because I hate working with package dependencies and can’t be bothered to RTFM. Learn from my mistakes.</p><ul><li><p>You don’t need to compute the MSE on a 1024x1024 image if the pixel-art is really 24x24. Just resize the image down and work with those images instead.</p></li><li><p>You may be able to get away with computing the MSE of the greyscale image, saving time versus computing it for the RGB version.</p></li><li><p>You don’t need GPU acceleration if you are working sequentially with small images, trying to load data into and out of the GPU just makes things slower.</p></li><li><p>If you do need GPU acceleration, RTFM and use frameworks made for dealing with GPUs and your specific type of problem</p></li><li><p>Use Conda or any environment manager really.</p></li><li><p>Let me repeat. USE CONDA.</p></li></ul><p>Eventually, I had a working algorithm and I started tweaking. It was close, but not perfect. It seemed to have a propensity for matching dark backgrounds. It dawned on me that really all we care about is the BGAN itself, not the background. I adjusted the array computation so that the MSE was only calculated on the center 1/3rd of each image. After some manual review of the results, I determined that an MSE of less than 30 was an exact match. Anything over that was close, but no cigar.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b0295fc5efc85b86013c205760e8e8926bee807384f7b9ccf7d51566ce91dcf7.png" alt="Examples of the top 3 matches for a target image with MSE scores listed." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Examples of the top 3 matches for a target image with MSE scores listed.</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/0c3e8f9d25d6266ca87d1219af0b1d131059ad8a4d43f8987e276f09931f6688.png" alt="Examples of the top 3 matches for a target image with MSE scores listed." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Examples of the top 3 matches for a target image with MSE scores listed.</figcaption></figure><p>With great excitement, I found that we now have 2649 image-label pairs. Naively, I assumed this was all we needed, this must be the ground truth I keep reading about! I loaded up the images into the U2Net_Train.py script that had been kindly included in the repository, edited what needed editing, and just like that, my machine was learning! After a few hours of training, I eagerly loaded up the newly trained model into the image-background-removal-tool and tried a test folder of 100 images.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1020a0b4e7530e5f83f030905661fd2bf41f556b52692b3fdb468be0ea3434b1.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/92e6ef0781e3064f5a1afa604225aaee82f8378794f95484d5a1c86c7030d4f0.png" alt="First pass training results…. something’s off" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">First pass training results…. something’s off</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b27672d3f0739c8bc57ad3b8343c02bf68014c9ede7f817d5805bd9b79acab79.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/deb235514bbb5a264a2d87749b971ee3ca4cfb6ecf0d4c4ae85ca1ade9f22ac3.png" alt="First pass training results…. something’s off" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">First pass training results…. something’s off</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/0a05e5734b5e78f458ebf5b94e2c942a11b4b1eb261d36469ffa2eb8088fee8b.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/9f124a9a49ac7b8b5429268b117437dc182be40ca71b7939182effe7628a089b.png" alt="First pass training results…. something’s off" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">First pass training results…. something’s off</figcaption></figure><p>Clearly, there was something wrong. Anyone familiar with the this topic will probably spot it right away. The hair and glasses being removed was a breadcrumb that led me to the truth. Turns out, what I thought was “ground truth” was not exactly what the U2Net model considered ground truth. The model is attempting to predict or infer a background MASK. The image removal tool uses this mask to do the actual background removal. Ground truth for this model is actually a black and white image, with white denoting fully opaque, and black denoting fully transparent.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/4ed34b1646cbe2b8b56e33e5db7fd90ae004adcbc7816aac650045da43820893.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/fc9a85c6916ddd46883460a3d4a542df9052deac622964446f33e62d52c580e0.png" alt="Mask versus Image with no background" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Mask versus Image with no background</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ee13d16caf0e6f90091bf90344b5f8d7e1a89f40394a99f6f7df1cdb0afbcf94.png" alt="Actual Image, BGAN# 6941" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Actual Image, BGAN# 6941</figcaption></figure><p>To address this, I wrote a program to extract the alpha channel from each image and then save it as a greyscale, giving us the masks we needed. Additionally, to help avoid overfitting, I had the program rotate every 7th image a few degrees off axis, as well as its associated mask. This rotation was in addition to a random 90, 180, or 270 degree base rotation, giving the training set a little bit of variance from the highly orthogonal pixel art.</p><p>I played with masks that had an alpha channel value that varied from 0–255, which I called soft masking, and also where it was binary, either 0 or 255, which I called hard masking. Additionally, I generated removal results using a purely color distance equation that simple compared each pixel to the value of the 0,0 pixel in terms of color distance.</p><p>After making these adjustments and checkpointing a few generations of the model, we finally have some useable results!</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e470ef619bcf8f296f8d8acf061f308296f0b39ac3247e172ecd85c0211c1c3d.png" alt="BGAN 26 BG Removal Model Comparison" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">BGAN 26 BG Removal Model Comparison</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b164cec31623791f14db4e4ee7b495be2a708e923e53729cb173139bdef15e3a.png" alt="BGAN 72 BG Removal Model Comparison" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">BGAN 72 BG Removal Model Comparison</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2784c4089dffa7d80285ff8fcf9aa9bb50a4efb8715d24a873cd12ab7d4caa1c.png" alt="BGAN 422 BG Removal Model Comparison" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">BGAN 422 BG Removal Model Comparison</figcaption></figure><p>As you can see, the manual and soft models seem to be the most consistently accurate, but for automatic application to 8000+ images there as no single model that I felt confident enough in to place full and complete trust in.</p><p>As a result, I am looking to the BGAN community and the internet at large to join me in crowdsource the final sort. I have waded into the surprisingly non trivial world of deploying a full stack interactive website, and am somewhere between proud and embarrassed to ask anyone interested in contributing to head over to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://bgans.rocks/">http://bgans.rocks</a> and start voting on which background removal you feel is most accurate!</p><p>I have a lot going on IRL but I will clean up my code and create a github repo as I plan to follow up this post with a more technical writeup for other groups to potentially re-use this workflow on their own collections. Part 2 publication date TBD….</p>]]></content:encoded>
            <author>witrebel@newsletter.paragraph.com (_Witrebel)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/8a4c3e37d7d4d55fac08f32ddf686f68264b579614b0875ea6bcbd8f70e2c32c.png" length="0" type="image/png"/>
        </item>
    </channel>
</rss>