Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

thanks, sharing an enhancement as i'm obliged to for open source #1

Open
experiment9123 opened this issue Jun 30, 2021 · 2 comments
Open

Comments

@experiment9123
Copy link

experiment9123 commented Jun 30, 2021

This is a great little tool.
Sorry I haven't done this as a propper pull request (i'm doing this quite adhoc) but here's a little modification I have made to this, which saves a kind of AO in the alpha channel of the output files. I have a couple of other extra enhancements in mind for my workflow. this would want to be a commandline option I guess, and would need a couple of control parameters (the size of the shadow gaussian, the bias, and whether to combine it or not)

from PIL import Image
import math

def normalized(a):
    
    factor = 1.0/math.sqrt( np.sum(a*a)) # normalize
    return a*factor

def my_gauss(im):
	im_smooth = im.astype(float)
	kernel = np.array([0.5,1.0,0.5]).astype(float);
	kernel=normalized(kernel)

	im_smooth = scipy.ndimage.convolve(im_smooth, kernel[np.newaxis])
	im_smooth = scipy.ndimage.convolve(im_smooth, kernel[np.newaxis].T)

	return im_smooth

#calculate a local internal shadowing/AO aproximation using 'difference of gaussians'
def shadow(im):
    im1 = im.astype(float)
    im0 = im1.copy()
    im00 = im1.copy()
    im000 = im1.copy()
    for i in range(0,2):
        im00 = my_gauss(im00)

    for i in range(0,64):
        im0 = my_gauss(im0)

    for i in range(0,128):
        im1 = my_gauss(im1)
    im000=normalized(im000)
    im00=normalized(im00)
    im0=normalized(im0)
    im1=normalized(im1)
    im00=normalized(im00)

    shadow=im00*2.0+im000-im1*2.0-im0 # np.clip(im1, 0.0, 1000000.0)
    shadow=normalized(shadow)
    mean = np.mean(shadow)
    rmse = rms_error(shadow)
    shadow = np.clip(shadow, mean-rmse*2.0,mean+rmse*0.5)

    return shadow

# ....
# added to the end of main()

   # save the pure normal map and AO/shadow images as seperatejpgs
    scipy.misc.imsave("normal.jpg", normal_map)


    im_shadow = shadow(im)



    scipy.misc.imsave("shadow.jpg", im_shadow)

    # read these images back in, and combine them to make an image with RGB=normal, Alpha=AO
    # really I did this because i couldn't get it working from numpy arrays directly.
    imgsh=Image.open("shadow.jpg")
    #imgsh.show()
    imgnorm=Image.open("normal.jpg")
    #imgnorm.show()
    imgnormao = np.zeros( (img.size[0],img.size[1],4), np.float)
    imgnormao[ :, :, 0:3] = np.asarray(imgnorm)[:,:,0:3]   #RGB = normal
    imgnormao[ :, :, 3] = np.asarray(imgsh)[:,:]                #Alpha = AO

    scipy.misc.imsave(output_file, imgnormao)
    imgnormao=Image.open(output_file)           # save the RGBA image containing Normal,AO





@experiment9123 experiment9123 changed the title thanks, sharing an enhancement as i'm obliged to by GPL thanks, sharing an enhancement as i'm obliged to for open source Jun 30, 2021
@Mehdi-Antoine
Copy link
Owner

Hi,
Thanks for your feedback, your enhancements sound interesting. Unfortunately I haven't used python and numpy for a very long time...
I would be thankful if you could create a proper pull request so that i can try and validate your code !

@experiment9123
Copy link
Author

experiment9123 commented Jun 30, 2021

ok i'll see if i can clean it up in a propper branched repo . meanwhile for reference heres an example of what it does (output with rgb normal, alpha shadowing from hand drawn greyscale input)
original greyscale
block
"AO"(internal shadowing) only
shadow
normals only
normal
Final output: combined RGB=normal,Alpha=AO
block_nm

michal212345 added a commit to michal212345/NormalMapGenerator that referenced this issue Oct 22, 2022
Updated the script to work on 3.9.13 with all the latest libraries.
Included the code from Mehdi-Antoine#1 Issue, the AO code.
Adjusted the code for performance. (Any better suggestions are welcome)
Added search folder for batch conversions.
Added Multiprocessing for the most optimal speed.
Added saving to separate folders for best organization.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants