Ejemplo n.º 1
0
def deconvolve_image(imagefile, kernel, vb=False):
	
##------------------------------------------------------------
	## Read in image
	
	## Determine image file type and get pixels
	try:
		imgext = os.path.splitext(imagefile)[1]
		if imgext==".fits":
			imgarr = fits_pix(imagefile)
		elif imgext==".png":
			assert False, "Cannot handle PNG format."
			
		## For some reason the image is flipped at this point, so un-flip
		imgarr = imgarr[::-1,:]
	
	## Or, if the imagefile is already an array	
	except AttributeError:
		imgarr = imagefile

##------------------------------------------------------------
	## Read in kernel
	
	## Distinguish between array-kernel and file-kernel
	if type(kernel) is str:	
		## Ensure the right kernel file has been selected
		if "PSFtoGauss" in kernel:
			kernel = numpy.loadtxt(kernel)
		else:
			print "DeconvolveToTargetPSF.py: deconvolve_image: wrong kernel file. Abort."
			return
	elif type(kernel) is numpy.array:
		pass
	
	## Kernel dimensions
	kernel_h,kernel_w = kernel.shape	
	
	#scipy.misc.imsave("../doc/Images/kernel.png", kernel)				#####
	#scipy.misc.imsave("../doc/Images/image.png",imgarr)					#####
##------------------------------------------------------------
	
	## Have kernel and original image; now we need to solve the matrix equation
	## Kx = b, where K is kernel, x is target image, and b is our observed image.
	
	## FIRST, dimensions of data image should be greater than those of scene
	## to ensure a stable solution.
	## Pad so that the scene has same dimensions of original data.
	refimg_dim = imgarr.shape
	refimg_size = imgarr.size
	obsimg_dim = numpy.array(imgarr.shape) + numpy.array(kernel.shape) - 1
	obsimg_size = obsimg_dim[0]*obsimg_dim[1]	
	
	
	## SECOND, construct matrix K from kernel array.	
	## kernmat should be obsimg_size by refimg_size
			
	## What is first row of kernmat?
	krow = numpy.zeros(refimg_size)
	for i in range(kernel_h):
		j = i*refimg_dim[0]	## Stride number
		krow[j:j+kernel_w] = kernel[i,:]
	## First column of kernmat (declare too large)
	kcol = numpy.zeros(obsimg_size); kcol[0]=krow[0]
	
	## Create dense Toeplitz matrix (not square)
	## This contains all the relevant rows; we'll chop it up later
	kernmat = scipy.linalg.toeplitz(kcol,krow)	
	
	## Some rows of the kernel matrix will be no good -- they represent pixel where the convolution
	## oversteps the image border
		## There must be a better way of doing this
	badrow = [numpy.arange(i*refimg_dim[0]-kernel_w+2, i*refimg_dim[0]+1) for i in range(1,refimg_dim[1])]
	## Delete spurious rows
	kernmat = numpy.delete(kernmat, badrow, axis=0)	
	## Also delete end rows from declaring kcol too large
		##convimgsiz is how big the kernel matrix should be if we are true to convolution
	convimgsiz = (refimg_dim[0]-kernel.shape[0]+1)*(refimg_dim[1]-kernel.shape[1]+1)
	kernmat = kernmat[:convimgsiz,:]
	
	#scipy.misc.imsave("../doc/Images/kernmat.png", kernmat)				#####
	
	## Now we need to pad out the kernel matrix to reflect padding of the data image	
	## do inner bits
	insertionrow = numpy.arange(refimg_dim[0]-kernel.shape[0]+2, convimgsiz, refimg_dim[0]-kernel.shape[0]+1).repeat(2*(obsimg_dim[0]-imgarr.shape[0]))
	kernmat = numpy.insert(kernmat, insertionrow, numpy.zeros(refimg_size), axis=0)
	## do ends
	thickpad = numpy.zeros([(obsimg_dim[0]+1)*(obsimg_dim[0]-imgarr.shape[0]),refimg_size])
	kernmat = numpy.append(kernmat, thickpad, axis=0)
	kernmat = numpy.append(thickpad, kernmat, axis=0)
	
	#scipy.misc.imsave("../doc/Images/kernmat_pad.png", kernmat)				#####
	
	## Don't need these any more
	kcol=None; krow=None; badrow=None; insertionrow=None; thickpad=None
	scipy.misc.imsave("kernmat.png",kernmat)
	
	## Turn dense kernmat into a sparse matrix
	#kernmat = scipy.sparse.dia_matrix(kernmat)

	
	## THIRD, construct vector b from observed image
	## This is padded with zeros so to make the matrix equation well-defined
	imgvec = pad(obsimg_dim, imgarr).flatten()
	
	#scipy.misc.imsave("../doc/Images/image_pad.png", imgvec.reshape(obsimg_dim))				#####
		
	## FOURTH, solve the equation Kx = b
	## The system of equations is UNDERdetermined
	t0=time.time()
	
	## Decide whether to use initial guess or not
	if False:
		print "Using intital guess."
		## Make initial guess; must be conformable
		refimg0 = shave(refimg_dim, imgarr).flatten()
		## Solve matrix equation K*(dx)=res
		residual = imgvec-numpy.dot(kernmat,refimg0)
		#correction,istop,itn = scipy.sparse.linalg.lsqr(kernmat, residuals, calc_var=False)[:3]
		correction,resi = numpy.linalg.lstsq(kernmat, residual)[:2]
		## Add initial solution to correction
		refimgvec = refimg0 + correction
		## Tidy up
		correction = None; residual = None; refimg0 = None
		
	## Or just straight solve
	else:
		## Account for noise
		#####
		## Sparse method or regular
		#refimgvec,istop,itn,r1norm,r2norm = scipy.sparse.linalg.lsqr(kernmat, imgvec, calc_var=False)[:5]
		refimgvec,resi = numpy.linalg.lstsq(kernmat, imgvec)[:2]
	
	if vb:
		print "image_deconvolve: least-squares converged to reference image in",\
					round(time.time()-t0,2),"seconds."

##------------------------------------------------------------					
	## Check: reverse procedure
	check = False
	if check is True:
		resi = (numpy.dot(kernmat,refimgvec)-imgvec).reshape(obsimg_dim)
		scipy.misc.imsave("check_resi.png", resi)
		scipy.misc.imsave("check_recon.png", numpy.dot(kernmat,refimgvec).reshape(obsimg_dim))
					
##------------------------------------------------------------
	## Reshape into an image
	refimg = refimgvec.reshape(refimg_dim)
	
##------------------------------------------------------------	

	## Outfile name
	try:
		imagedir,imagename = os.path.split(imagefile)
		info = imagename[imagename.find("CFHT"):imagename.find("sci")+3]
		outfile = imagedir+"/gDeconvolved_"+info
		header = fits_hdr(imagefile)
	except (TypeError, AttributeError):
		## If the input was in array format
		outfile = "deconvolved"
		header = None
		
##------------------------------------------------------------	
	
	## Rescale (linear stretch)
	if True:
		## Scaling parameters
		vmin,vmax = stretch_params(refimg)
		## Stretch
		refimg = linear_rescale(refimg, vmin, vmax)
		## Modify filename
		outfile = outfile+"_rescaled"
	
	## Delete pre-existing images
	if os.path.isfile(outfile+".fits"): os.remove(outfile+".fits")
	if os.path.isfile(outfile+".png"):  os.remove(outfile+".png")
	
	## Save image as FITS and as PNG
	#makeFITS(outfile+".fits", refimg, header)
	#scipy.misc.imsave(outfile+".png", refimg)
	if vb: print "DeconvolveToTargetPSF.py: deconvolve_image: image saved to",outfile+".fits"
	
	return refimg
Ejemplo n.º 2
0
def deconvolve_image(imagefile, kernel, vb=False):
	
##------------------------------------------------------------
	## Read in image
	
	## Determine image file type and get pixels
	imgext = os.path.splitext(imagefile)[1]
	if imgext==".fits":	imgarr = fits_pix(imagefile)
	elif imgext==".png": imgarr = png_pix(imagefile) ## Doesn't work
	
	## For some reason the image is flipped at this point, so un-flip
	imgarr = imgarr[::-1,:]
	
	## Filter out noise
	imgarr[imgarr<cutoff] = 0.0

##------------------------------------------------------------
	## Read in kernel
	
	## Distinguish between array-kernel and file-kernel
	if type(kernel) is str:	
		## Ensure the right kernel file has been selected
		if "PSFtoGauss" in kernel:
			kernel = numpy.loadtxt(kernel)
		else:
			print "DeconvolveToTargetPSF.py: deconvolve_image: wrong kernel file. Abort."
			return
	elif type(kernel) is numpy.array:
		pass
	
	## Kernel dimensions
	kernel_h,kernel_w = kernel.shape
		
	# Should also check match with imagefile #
	
##------------------------------------------------------------	
	## Compute linalg objects from images
	
	## Honest dimensions for scene
	scene_dim = numpy.array(imgarr.shape)-numpy.array(kernel.shape)+1
	scene_siz = scene_dim[0]*scene_dim[1]
	
##------------------------------------------------------------
	
	convmeth = "scipy"
	
	## Manual convolution
	if convmeth=="manual":	
	
		## 1D array for SCENE (convolved with Gaussian)
		g_sc = numpy.empty(imgarr.size)#scene_siz
		## 1D array for IMAGE
		stride = imgarr.shape[0]
		imgarr = imgarr.flatten()

	##------------------------------------------------------------
	## Manual matrix product
		
		## Initialise kernel "vector"
		len_krn_lin = (stride)*(kernel_h-1)+kernel_w	## Still keeps a lot of zeros
		krn_lin = numpy.zeros(len_krn_lin)
		## Loop over slices in the kernel image
		for j in range (kernel_h):
			startcol = j*stride
			krn_lin[startcol:startcol+kernel_w] = kernel[j,:]
			
		t0 = time.time()
		## Perform linalg product
			## i labels the scene pixel and the slice in the original
		for i in range (scene_siz):
			imageslice = imgarr[i:i+len_krn_lin]
			g_sc[i] = numpy.dot(krn_lin,imageslice)
		if vb: print "DeconvolveToTargetPSF.py: deconvolve_image: vector multiplication took",\
					round(time.time()-t0,2),"seconds."
		
		## Delete spurious elements (from overlapping)
		i=len(g_sc)
		while i>=0:
			if i%stride+kernel_w > stride:
				g_sc = numpy.delete(g_sc,i)
			i-=1
		## Delete spurious elements from declaring it too big
		g_sc = numpy.delete(g_sc,slice(scene_siz-len(g_sc)-1,-1))
		if scene_siz-len(g_sc): print "LINE #"+str(lineno())+": size discrepancy"


##------------------------------------------------------------
	
	elif convmeth=="scipy":
		t0=time.time()
		## Do convolution using scipy
		imgarr = numpy.array(imgarr, dtype="float64")
		g_sc = convolve(imgarr, kernel, mode="valid")
		if vb: print "DeconvolveToTargetPSF.py: deconvolve_image: SciPy convolution took",\
					round(time.time()-t0,2),"seconds."
		
	else:
		print "LINE #"+str(lineno())+": convmeth error, abort."
		return
		
##------------------------------------------------------------
	
	## Reshape
	if g_sc.shape[0]!=scene_dim[0] or g_sc.shape[1]!=scene_dim[1]:
		if vb: print "DeconvolveToTargetPSF.py: deconvolve_image: reshaping."
		try:
			g_sc = g_sc.reshape(scene_dim)
		except ValueError:	
			print "DeconvolveToTargetPSF.py: deconvolve_image: output has wrong shape. Investigate."

##------------------------------------------------------------
	
	## Filter out (computer) noise
	g_sc[g_sc<cutoff] = 0.0
	
	## Outfile name
	imagedir,imagename = os.path.split(imagefile)
	info = imagename[imagename.find("CFHT"):imagename.find("sci")+3]
	outfile = imagedir+"/gDeconvolved_"+info
	
	## Rescale (linear stretch)
	if 1:
		## Scaling parameters
		vmin,vmax = stretch_params(g_sc)
		## Stretch
		g_sc = linear_rescale(g_sc, vmin, vmax)
		## Modify filename
		outfile = outfile+"_rescaled"
	
	## Delete pre-existing images
	if os.path.isfile(outfile+".fits"): os.remove(outfile+".fits")
	if os.path.isfile(outfile+".png"):  os.remove(outfile+".png")
	
	## Save image as FITS and as PNG
	makeFITS(outfile+".fits", g_sc)
	scipy.misc.imsave(outfile+".png", g_sc)
	if vb: print "DeconvolveToTargetPSF.py: deconvolve_image: image saved to",outfile+".fits"
	
	return None
Ejemplo n.º 3
0
def deconvolve_image(imagefile, kernel, vb=False):

    ##------------------------------------------------------------
    ## Read in image

    ## Determine image file type and get pixels
    try:
        imgext = os.path.splitext(imagefile)[1]
        if imgext == ".fits":
            imgarr = fits_pix(imagefile)
        elif imgext == ".png":
            assert False, "Cannot handle PNG format."

        ## For some reason the image is flipped at this point, so un-flip
        imgarr = imgarr[::-1, :]

    ## Or, if the imagefile is already an array
    except AttributeError:
        imgarr = imagefile

##------------------------------------------------------------
## Read in kernel

## Distinguish between array-kernel and file-kernel
    if type(kernel) is str:
        ## Ensure the right kernel file has been selected
        if "PSFtoGauss" in kernel:
            kernel = numpy.loadtxt(kernel)
        else:
            print "DeconvolveToTargetPSF.py: deconvolve_image: wrong kernel file. Abort."
            return
    elif type(kernel) is numpy.array:
        pass

    ## Kernel dimensions
    kernel_h, kernel_w = kernel.shape

    #scipy.misc.imsave("../doc/Images/kernel.png", kernel)				#####
    #scipy.misc.imsave("../doc/Images/image.png",imgarr)					#####
    ##------------------------------------------------------------

    ## Have kernel and original image; now we need to solve the matrix equation
    ## Kx = b, where K is kernel, x is target image, and b is our observed image.

    ## FIRST, dimensions of data image should be greater than those of scene
    ## to ensure a stable solution.
    ## Pad so that the scene has same dimensions of original data.
    refimg_dim = imgarr.shape
    refimg_size = imgarr.size
    obsimg_dim = numpy.array(imgarr.shape) + numpy.array(kernel.shape) - 1
    obsimg_size = obsimg_dim[0] * obsimg_dim[1]

    ## SECOND, construct matrix K from kernel array.
    ## kernmat should be obsimg_size by refimg_size

    ## What is first row of kernmat?
    krow = numpy.zeros(refimg_size)
    for i in range(kernel_h):
        j = i * refimg_dim[0]  ## Stride number
        krow[j:j + kernel_w] = kernel[i, :]
    ## First column of kernmat (declare too large)
    kcol = numpy.zeros(obsimg_size)
    kcol[0] = krow[0]

    ## Create dense Toeplitz matrix (not square)
    ## This contains all the relevant rows; we'll chop it up later
    kernmat = scipy.linalg.toeplitz(kcol, krow)

    ## Some rows of the kernel matrix will be no good -- they represent pixel where the convolution
    ## oversteps the image border
    ## There must be a better way of doing this
    badrow = [
        numpy.arange(i * refimg_dim[0] - kernel_w + 2, i * refimg_dim[0] + 1)
        for i in range(1, refimg_dim[1])
    ]
    ## Delete spurious rows
    kernmat = numpy.delete(kernmat, badrow, axis=0)
    ## Also delete end rows from declaring kcol too large
    ##convimgsiz is how big the kernel matrix should be if we are true to convolution
    convimgsiz = (refimg_dim[0] - kernel.shape[0] + 1) * (refimg_dim[1] -
                                                          kernel.shape[1] + 1)
    kernmat = kernmat[:convimgsiz, :]

    #scipy.misc.imsave("../doc/Images/kernmat.png", kernmat)				#####

    ## Now we need to pad out the kernel matrix to reflect padding of the data image
    ## do inner bits
    insertionrow = numpy.arange(refimg_dim[0] - kernel.shape[0] + 2,
                                convimgsiz,
                                refimg_dim[0] - kernel.shape[0] + 1).repeat(
                                    2 * (obsimg_dim[0] - imgarr.shape[0]))
    kernmat = numpy.insert(kernmat,
                           insertionrow,
                           numpy.zeros(refimg_size),
                           axis=0)
    ## do ends
    thickpad = numpy.zeros([
        (obsimg_dim[0] + 1) * (obsimg_dim[0] - imgarr.shape[0]), refimg_size
    ])
    kernmat = numpy.append(kernmat, thickpad, axis=0)
    kernmat = numpy.append(thickpad, kernmat, axis=0)

    #scipy.misc.imsave("../doc/Images/kernmat_pad.png", kernmat)				#####

    ## Don't need these any more
    kcol = None
    krow = None
    badrow = None
    insertionrow = None
    thickpad = None
    scipy.misc.imsave("kernmat.png", kernmat)

    ## Turn dense kernmat into a sparse matrix
    #kernmat = scipy.sparse.dia_matrix(kernmat)

    ## THIRD, construct vector b from observed image
    ## This is padded with zeros so to make the matrix equation well-defined
    imgvec = pad(obsimg_dim, imgarr).flatten()

    #scipy.misc.imsave("../doc/Images/image_pad.png", imgvec.reshape(obsimg_dim))				#####

    ## FOURTH, solve the equation Kx = b
    ## The system of equations is UNDERdetermined
    t0 = time.time()

    ## Decide whether to use initial guess or not
    if False:
        print "Using intital guess."
        ## Make initial guess; must be conformable
        refimg0 = shave(refimg_dim, imgarr).flatten()
        ## Solve matrix equation K*(dx)=res
        residual = imgvec - numpy.dot(kernmat, refimg0)
        #correction,istop,itn = scipy.sparse.linalg.lsqr(kernmat, residuals, calc_var=False)[:3]
        correction, resi = numpy.linalg.lstsq(kernmat, residual)[:2]
        ## Add initial solution to correction
        refimgvec = refimg0 + correction
        ## Tidy up
        correction = None
        residual = None
        refimg0 = None

    ## Or just straight solve
    else:
        ## Account for noise
        #####
        ## Sparse method or regular
        #refimgvec,istop,itn,r1norm,r2norm = scipy.sparse.linalg.lsqr(kernmat, imgvec, calc_var=False)[:5]
        refimgvec, resi = numpy.linalg.lstsq(kernmat, imgvec)[:2]

    if vb:
        print "image_deconvolve: least-squares converged to reference image in",\
           round(time.time()-t0,2),"seconds."

##------------------------------------------------------------
## Check: reverse procedure
    check = False
    if check is True:
        resi = (numpy.dot(kernmat, refimgvec) - imgvec).reshape(obsimg_dim)
        scipy.misc.imsave("check_resi.png", resi)
        scipy.misc.imsave("check_recon.png",
                          numpy.dot(kernmat, refimgvec).reshape(obsimg_dim))

##------------------------------------------------------------
## Reshape into an image
    refimg = refimgvec.reshape(refimg_dim)

    ##------------------------------------------------------------

    ## Outfile name
    try:
        imagedir, imagename = os.path.split(imagefile)
        info = imagename[imagename.find("CFHT"):imagename.find("sci") + 3]
        outfile = imagedir + "/gDeconvolved_" + info
        header = fits_hdr(imagefile)
    except (TypeError, AttributeError):
        ## If the input was in array format
        outfile = "deconvolved"
        header = None

##------------------------------------------------------------

## Rescale (linear stretch)
    if True:
        ## Scaling parameters
        vmin, vmax = stretch_params(refimg)
        ## Stretch
        refimg = linear_rescale(refimg, vmin, vmax)
        ## Modify filename
        outfile = outfile + "_rescaled"

    ## Delete pre-existing images
    if os.path.isfile(outfile + ".fits"): os.remove(outfile + ".fits")
    if os.path.isfile(outfile + ".png"): os.remove(outfile + ".png")

    ## Save image as FITS and as PNG
    #makeFITS(outfile+".fits", refimg, header)
    #scipy.misc.imsave(outfile+".png", refimg)
    if vb:
        print "DeconvolveToTargetPSF.py: deconvolve_image: image saved to", outfile + ".fits"

    return refimg