Tumgik
#some more ai + overpainting stuff
chroma-game · 1 year
Photo
Tumblr media
Formless hue, ethereal grace, the faceless man takes his place
160 notes · View notes
moodr1ng · 1 year
Text
i fully agree that the phenomenon of ai art taking over artist jobs is concerning and fucked up, but also ppl now say "itll make people give up art/not want to make art bc you cant get paid for it" and i just.. i dont think people typically get into art expecting to live off of it you guys. im p sure art is not generally considered a stable, assured career, and also the semi-professional artists who are losing work to this (because its not industry artists, people employed by game or animation studios or under contract for comics, etc losing work, its semi-amateur artists who do commissions for supplementary income) were not and are not getting the benefits of stable and decent employment for art already. if "i cant make money off this" turned people off of digital art, there wouldnt be many people getting into it to begin with
13 notes · View notes
retronator · 8 months
Text
Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media
I never played Karateka in the 80s, but as a big fan of Prince of Persia and Jordan Mechner's journals, I was stoked to hear that an interactive documentary about Jordan's prototypical cinematic platformer was in the works by Digital Eclipse.
Released this week, The Making of Karateka on the surface looks like any other game you buy through Steam ($20, Windows-only), GOG, or whichever favorite store or console you prefer (available also for Xbox, PS4/5, Switch). Once the thing loads though, you really get 3 things: a documentary, the original Karateka, and a new remaster.
The documentary part is an audio-visual slideshow retelling Jordan's development story starting with his teenage years pitching his earlier title Deathbounce to the publishing house Brøderbund. It's an interesting look into the iterative process, seen through correspondence letters, journal entries, and many playable builds at various stages of completion. After we reach the eventual rejection of that title, Jordan comes back with a prototype of a visual-narrative experience unseen on home computers. We get to follow Karateka's full life cycle from pre- to post-production, ending with the conception of its sequel (which eventually turned into Prince of Persia). It's a real treasure trove! Fellow pixel artists will appreciate the many graph-paper sketches and interactive overlays of final game sprites compared to rotoscoped outlines and filmed footage. There are also video segments, from a comprehensive breakdown of the music to interviews with other developers reflecting on the impact Jordan's games had on their careers. You'll even encounter a fan letter signed by the one and only "John Romero, Disciple of the Great Jordan and worshipper of the Magnificent Mechner!" (I kid you not, you can't make this stuff up).
Perhaps just as crucial for an interactive documentary like this, you can launch any of the floppy disks in the emulator, trying out various iterations and ports of Karateka.
Tumblr media Tumblr media Tumblr media
The emulation is fantastic and lets you fiddle with display settings (monochrome or color display, scanlines, pixel perfect or zoomed) as well as enhance the frame rate. You can even rewind the many deaths you will face if you've never played the game before (like me). If you spend some more time obsessing over the weird artifacts of the Apple II hi-res graphics, you might even go down the rabbit hole of realizing that on the Apple II you didn't really paint colors as much as you used different monochrome dithering patterns that the graphics display would then turn into 4 different hues. A fascinating learning experience if you include some of your own research online!
youtube
Add to this the Commodore 64 and the Atari 8-bit versions to compare how the graphics got adapted across the earlier ports and you have a nice way to relieve the mid-80s with a bit of help from modern emulation (I did beat the C64 version without rewinding though!). I'd love to see more art from the other remakes, especially the 16-bit Atari ST port, but I understand their decision to omit playable versions of those due to the lower quality on the gameplay side of the translations.
This brings us to the final part of the package, the modern remaster. Unlike the 2012 complete reimagining of the game (with 3D graphics and all), Digital Eclipse approached the remake as the ultimate port of the original to an imaginary system along the lines of a 90s VGA PC.
Tumblr media Tumblr media Tumblr media Tumblr media
It's well done. Some of the fully-redrawn scenes are a bit overpainted for my taste (I'd prefer a pixel art rendition of the castle than a blurry photographic collage, although there were many games in the 90s that did take this approach), but the in-game graphics are really in style, including the smooth animations that are like one would imagine granted a beefier CPU. It's also a sort of director's cut with previously unseen scenes added, in particular, the battle with the leopard as a clever action-puzzle in the middle. The AI is unfortunately even less challenging than Jordan's implementation. As great as the 6-move fighting system could have been, you yet again resort to simply kicking away opponents as they tirelessly crawl into your range. There isn't even the nuance from the original where you were the one who had to approach some enemies with skilled timing. On the other hand, you now have optional goals and achievements that make the repetitive/easy combat work in your favor (stringing various combos, beating opponents or the level under a time limit …). As the Digital Eclipse president Mike Mika admits at the end of the welcome commentary mode, they didn't manage to achieve their perfect port, but they did come close.
In conclusion, I thoroughly enjoyed playing both the original as well as the remake and while the combat system lacks any sort of depth beneath its stunning animations, Karateka is instead a monumental experience for its presentation. Big characters with personality and realistic motion are displayed through cinematic camera cuts and story vignettes (3 years before Ron Gilbert came up with the word "cutscene"). There are details like animating the unfortunate falling off the cliff at the start of the game, or respectfully bowing to the first guard as they bow in return. Jordan's creative work is precious and worth the attention this release gifts it.
I highly recommend The Making of Karateka to all retro gamers and/or game developers for its immersive documentation which provides an experience that goes beyond the usual video documentaries. It's interactive—just like the subject it's talking about—something I want to see more in the future. And if the $20 by any chance seems high to you, consider that the original retailed at $35 (and that was in 1984 dollars).
youtube
77 notes · View notes
phemiec · 1 year
Note
i've seen a lot of artists treat ai art like the end of art / art careers for a lot of people, but you seem really positive about it and i'd love to see you expand more on that!!
what people are afraid of with AI art (or, the semi-valid fears anyway) are that they will loose their money making niche, which isn’t an art issue it’s a capitalism issue. We are all being made redundant in a system that is designed without putting human beings first. That’s the same for everyone and frankly maybe the fact that artists are realizing we aren’t exempt from that will create more motivation to create a better system, or at least more art exploring disenfranchisement and anti-capitalism.
Humans beings have always been compelled to make art using whatever tools we’ve had available, it predates all recorded history and that has not and will not change, just like the invention of paper, ink, paints, digital art in general, AI is a creative tool people can use to explore concepts and get inspiration. and it opens up art and creativity and the experience of creating visual art to an even wider array of people, people who haven’t had the time or inclination or opportunity to spend thousands of hours learning things like perspective, anatomy, colour theory etc, can now experience their imagination coming to life visually which is fucking incredible. And the people who already like drawing and painting will still do all that stuff. And yes, some people who may have hired concept designers may just use ai instead, but more likely, concept artists will be hired and utilized differently.
as someone who studied concept art in college, the industry is already using tons of references, overpainting, 3d modeling, the easier and more effeciently you can create lots of concepts quickly the better, it’s not like fine art, you are making art mostly piecemeal from a dozen sources, and using your knowledge and creativity to make all of your inspirations cohesive, stuff like Midjourney can really only help in that respect.
will some people maybe miss out on commission work? Sure, but again, that’s like saying we shouldn’t create robots capable of nano surgery because it will make surgeons less valuable. If we lived in a post scarcity world where people were given universal basic income all of the fears about AI art would be replaced with wonder and curiosity, because we would just be able to create for creations sake.
anyway yeah tldr: artists aren’t immune to all the same bullshit that everyone else experiences under capitalism, the sooner we realize that the better. Stop gatekeeping art and creativity, everyone deserves the experience of creation, someone’s ability to generate a very cool piece of art easily without years of effort should not negate your enjoyment of your own journey as an artist. embrace chaos and fuck capitalism. ✌️👍
383 notes · View notes
therobotmonster · 1 year
Text
This Toy Does Not Exist: ReSculpt
Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media
An experiment of using Midjourney's Describe and Image Prompting functions to remaster previously-generated AI content.
A ways back I did This Toy Does Not Exist, using LookingGlassAI, by manually training a diffusion model on hundreds of action figure pictures. I was strongly limited by my processor and the resources at the time, and eventually moved to Midjourney as I can only afford so many art tools, and it was the more powerful option.
Tumblr media Tumblr media
For these images, I submitted the original This Toy Does Not Exist picture to Midjourney's describe feature. I then generated using the provided prompts, but also included the original image as an image prompt. Settings --s 50 --IW 2 --V 5 (style 50, image weight 2, version 5)
Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media
I then picked my favorite out of the sixteen images produced per base image (All AI art is curated, always remember that) . My goal, in general, was to produce stuff that still had that retro figure feel. Most of the stuff MJ produces is very modern, and my previous remaster attempts were similarly a little too polished and glyos-y for my vision.
Tumblr media Tumblr media
I've been toying with similar processes on my old style transfer pieces, and a lot of stuff made using the specialized Artbreeder generators.
The limitations are apparent. The wilder stuff that the more basic AI didn't know was atypical gets smoothed out. In some cases, that's a help, as more abstract stuff can be re imagined into something more cohesive, but that AI madness is blunted a bit, and I like that aspect.
Tumblr media Tumblr media
Of course, that's where human involvement comes in, as any of these that I might decide to actually sculpt will be changed through that process to fit my druthers of how it turned out. Because that's what AI makes well. Building blocks.
Explanations of the features used are under the fold. As everything here is autogenerated, it does not meet the minimum human expression threshold and is all in the public domain.
Describe is Midjourney's its own version of Clip Interrogator, which can derive a prompt from an image. It's looser than Clip Interrogator, gives multiple options, and generally makes stuff in similar vibes but doesn't match style or even subject matter closely without prompt editing. It essentially has the AI examine a picture, match its observed elements in its token-language, and then translate that back into an english-formatted prompt.
Image Prompting is an older feature that does essentially what Describe does, but it never translates the generated tokens back into words, and instead uses those tokens as a prompt, combined with a text prompt or at least one other image. These limitations are there to force novelty and prevent intentional overfitting/image copying, for the same reason the describe prompts are shorter and more vague than their Clip-Interrogator equivalents.
Image prompting is not the same as overpainting, wherein a base image is used in place of random JPG noise for the generation start. MJ doesn't do overpainting because of fears of its use for deepfakery and plagiarism. Ironically, that prevents people like me from sketching up our own layouts and using MJ to directly fill them in, but there's tradeoffs in every situation I suppose.
Not posting specific prompts because this post is already bloated AF. But anyone can use my technique.
46 notes · View notes
dreadjim · 2 years
Photo
Tumblr media
Power of this tech enables me to create this in spite of my busy time schedule~ my first graphic novel 'sample' page test where I :painted basic concept>use ai(stable,MJ,dalle etc) to inpainted (thereby preserving the style>generated samples of my 'offspring'> Overpaint to fix and beautify and then finally layout in Photoshop, created the rest of the stuff and adjusted/painted some more to finalize... Pretty stoked! Not sure if I have the time to do more of these but it is one of the bucket list checked for sure if I ever get to produce a full scale narrative/ip comic for this~ #dreadjim #graphicnovel #projecteve #aicollab #conceptdesign (at Singapore / Singapura / 新加坡 / சிங்கப்பூர்) https://www.instagram.com/p/CiO7Magr_24/?igshid=NGJjMDIxMWI=
0 notes
hackersandslackers · 6 years
Photo
Tumblr media
A Dirty Way of Cleaning Data (ft. Pandas & SQL)
Code Snippet Corner ft. Pandas & SQL
Warning The following is FANTASTICALLY not-secure. Do not put this in a script that's going to be running unsupervised. This is for interactive sessions where you're prototyping the data cleaning methods that you're going to use, and/or just manually entering stuff. Especially if there's any chance there could be something malicious hiding in the data to be uploaded. We're going to be executing formatted strings of SQL unsanitized code. Also, this will lead to LOTS of silent failures, which are arguably The Worst Thing - if guaranteed correctness is a requirement, leave this for the tinkering table. Alternatively, if it's a project where "getting something in there is better than nothing", this can provide a lot of bang for your buck. Actually, it's purely for entertainment purposes and not for human consumption. Let's say you were helping someone take a bunch of scattered Excel files and CSVs and input them all into a MySQL database. This is a very iterative, trial & error process. We certainly don't want to be re-entering a bunch of boilerplate. Pandas to the rescue! We can painlessly load those files into a DataFrame, then just export them to the db! Well, not so fast First off, loading stuff into a DB is a task all its own - Pandas and your RDBMS have different kinds of tolerance for mistakes, and differ in often-unpredictable ways. For example, one time I was performing a task similar to the one described here (taking scattered files and loading them into a DB) - I was speeding along nicely, but then ran into a speedbump: turns out Pandas generally doesn't infer that a column is a date unless you tell it specifically, and will generally parse dates as strings. Now, this was fine when the dates were present - MySQL is pretty smart about accepting different forms of dates & times. But one thing it doesn't like is accepting an empty string '' into a date or time column. Not a huge deal, just had to cast the column as a date: df['date'] = pd.to_datetime(df['date']) Now the blank strings are NaT , which MySQL knows how to handle! This was simple enough, but there's all kinds of little hiccups that can happen. And, unfortunately, writing a DataFrame to a DB table is an all-or-nothing affair - if there's one error, that means none of the rows will write. Which can get pretty annoying if you were trying to write a decent-sized DataFrame, especially if the first error doesn't show up until one of the later rows. Waiting sucks. And it's not just about being impatient - long waiting times can disrupt your flow. Rapid prototyping & highly-interactive development are some of Python's greatest strengths, and they are great strengths indeed! Paul Graham (one of the guys behind Y Combinator) once made the comparison between REPL-heavy development and the popularizing of oil paints (he was talking about LISP, but it's also quite true of Python, as Python took a lot of its cues from LISP): Before oil paint became popular, painters used a medium, called tempera , that cannot be blended or overpainted. The cost of mistakes was high, and this tended to make painters conservative. Then came oil paint, and with it a great change in style. Oil "allows for second thoughts". This proved a decisive advantage in dealing with difficult subjects like the human figure. The new medium did not just make painters' lives easier. It made possible a new and more ambitious kind of painting. Janson writes: Without oil, the Flemish Masters'conquest of visible reality would have been much more limited. Thus, from a technical point of view, too, they deserve to be called the "fathers of modern painting" , for oil has been the painter's basic medium ever since. As a material, tempera is no lesss beautiful than oil. But the flexibility of oil paint gives greater scope to the imagination--that was the deciding factor. Programming is now undergoing a similar change...Meanwhile, ideas borrowd from Lisp increasingly turn up in the mainstream: interactive programming environments, garbage collectgion, and run-time typing to name a few. More powerful tools are taking the risk out of exploration. That's good news for programmers, because it means that we will be able to undertake more ambitious projects. The use of oil paint certainly had this effect. The period immediately following its adoption was a golden age for painting. There are signs already that something similar is happening in programming. (Emphasis mine) From here: http://www.cs.oswego.edu/~blue/xhx/books/ai/ns1/section02/main.html A little scenario to demonstrate: Let's pretend we have a MySQL instance running, and have already created a database named items import pymysql from sqlalchemy import create_engine import sqlalchemy import pandas as pd cnx = create_engine('mysql+pymysql://analyst:badsecuritykills@localhost:3306/items) pd.io.sql.execute("""CREATE TABLE books( \ id VARCHAR(40) PRIMARY KEY NOT NULL \ ,author VARCHAR(255) \ ,copies INT)""", cnx) df = pd.DataFrame({ "author": ["Alice", "Bob", "Charlie"], "copies": [2, "", 7, ],}, index = [1, 2, 3]) #Notice that one of these has the wrong data type! df.to_sql(name='books',con=cnx,if_exists='append',index=False) #Yeah, I'm not listing this whole stacktrace. Fantastic package with some extremely helpful Exceptions, but you've gotta scroll a whole bunch to find em. Here's the important part: InternalError: (pymysql.err.InternalError) (1366, "Incorrect integer value: '' for column 'copies' at row 1") [SQL: 'INSERT INTO books (id, author, copies) VALUES (%(id)s, %(author)s, %(copies)s)'] [parameters: {'id': 2, 'author': 'Bob', 'copies': ''}] (Background on this error at: http://sqlalche.me/e/2j85) Soo, let's tighten this feedback loop, shall we? We'll iterate through the DataFrame with the useful iterrows() method. This gives us essentially an enum made from our DataFrame - we'll get a bunch of tuples giving us the index as the first element and the row as its own Pandas Series as the second. for x in df.iterrows(): try: pd.DataFrame(x[1]).transpose().to_sql(name='books', con=cnx, if_exists='append', index_label='id') except: continue Let's unpack that a bit. Remember that we're getting a two-element tuple, with the good stuff in the second element, so x[1] Next, we convert the Series to a one-entry DataFrame, because the Series doesn't have the DataFrame's to_sql() method. pd.DataFrame(x[1]) The default behavior will assume this is a single column with, each variable being the address of a different row. MySQL isn't going to be having it. Sooo, we transpose! pd.DataFrame(x[1]).transpose() And finally, we use our beloved to_sql method on that. Let's check our table now! pd.io.sql.read_sql_table("books", cnx, index_col='id') author copies id 1 Alice 2 It wrote the first row! Not much of a difference with this toy example, but once you were writing a few thousand rows and the error didn't pop up until the 3000th, this would make a pretty noticeable difference in your ability to quickly experiment with different cleaning schemes. Note that this will still short-circuit as soon as we hit the error. If we wanted to make sure we got all the valid input before working on our tough cases, we could make a little try/except block. for x in df.iterrows(): try: pd.DataFrame(x[1]).transpose().to_sql(name='books', con=cnx, if_exists='append', index=False,) except: continue This will try to write each line, and if it encounters an Exception it'll continue the loop. pd.io.sql.read_sql_table("books", cnx, index_col='id') author copies id 1 Alice 2 3 Charlie 7 Alright, now the bulk of our data's in the db! Whatever else happens, you've done that much! Now you can relax a bit, which is useful for stimulating the creativity you'll need for the more complicated edge cases. So, we're ready to start testing new cleaning schemes? Well, not quite yet... Let's say we went and tried to think up a fix. We go to test it out and... #Note that we want to see our exceptions here, so either do without the the try/except block for x in df.iterrows(): pd.DataFrame(x[1]).transpose().to_sql(name='books', con=cnx, if_exists='append', index=False, ) #OR have it print the exception for x in df.iterrows(): try: pd.DataFrame(x[1]).transpose().to_sql(name='books', con=cnx, if_exists='append', index_label='id') except Exception as e: print(e) continue #Either way, we get... (pymysql.err.IntegrityError) (1062, "Duplicate entry '1' for key 'PRIMARY'") [SQL: 'INSERT INTO books (id, author, copies) VALUES (%(id)s, %(author)s, %(copies)s)'] [parameters: {'id': 1, 'author': 'Alice', 'copies': 2}] (Background on this error at: http://sqlalche.me/e/gkpj) (pymysql.err.InternalError) (1366, "Incorrect integer value: '' for column 'copies' at row 1") [SQL: 'INSERT INTO books (id, author, copies) VALUES (%(id)s, %(author)s, %(copies)s)'] [parameters: {'id': 2, 'author': 'Bob', 'copies': ''}] (Background on this error at: http://sqlalche.me/e/2j85) (pymysql.err.IntegrityError) (1062, "Duplicate entry '3' for key 'PRIMARY'") [SQL: 'INSERT INTO books (id, author, copies) VALUES (%(id)s, %(author)s, %(copies)s)'] [parameters: {'id': 3, 'author': 'Charlie', 'copies': 7}] (Background on this error at: http://sqlalche.me/e/gkpj) The error we're interested is in there, but what's all this other nonsense crowding it? Well, one of the handy things about a database is that it'll enforce uniqueness based on the constraints you give it. It's already got an entry with an id value of 1, so it's going to complain if you try to put another one. In addition to providing a lot of distraction, this'll also slow us down considerably - after all, part of the point was to make our experiments with data-cleaning go faster! Luckily, Pandas' wonderful logical indexing will make it a snap to ensure that we only bother with entries that aren't in the database yet. #First, let's get the indices that are in there usedIDs = pd.read_sql_table("books", cnx, columns=["id"])["id"].values df[~df.index.isin(usedIDs)] author copies 2 Bob #Remember how the logical indexing works: We want every element of the dataframe where the index ISN'T in our array of IDs that are already in the DB This will also be shockingly quick - Pandas' logical indexing takes advantage of all that magic going on under the hood. Using it, instead of manually iteration, can literally bring you from waiting minutes to waiting seconds. Buuut, that's a lot of stuff to type! We're going to be doing this A LOT, so how about we just turn it into a function? #Ideally we'd make a much more modular version, but for this toy example we'll be messy and hardcode some paramaters def filterDFNotInDB(df): usedIDs = pd.read_sql_table("books", cnx, columns=["id"])["id"].values return df[~df.index.isin(usedIDs)] So, next time we think we've made some progress on an edge case, we just call... #Going back to the to_sql method here - we don't want to have to loop through every single failing case, or get spammed with every variety of error message the thing can throw at us. filterDFNotInDB(cleanedDF).to_sql(name='books', con=cnx, if_exists='append', index_label='id') Actually, let's clean that up even more - the more keys we hit, the more opportunities to make a mistake! The most bug-free code is the code you don't write. def writeNewRows(df): filterDFNotInDB(df).to_sql(name='books', con=cnx, if_exists='append', index_label='id') So, finally, we can work on our new cleaning scheme, and whenever we think we're done... writeNewRows(cleanedDF) And boom! Instant feedback!
- Matthew Alhonte
0 notes