Esempio n. 1
0
def debugPlot(imagePath,
              fitsWcsPath,
              tleFolder,
              photoTimeDelta=None,
              altitude=0,
              minElevation=10):
    """
    Plot the georeferenced image on a map. This allows to play with the image timestamp
    and mapping altitude.
    
    :param imagePath:
    :param fitsWcsPath:
    :param tleFolder:
    :param datetime.timedelta photoTimeDelta: amount to shift the image time (affects calculated
        camera position and therefore the geodetic coordinates)
    :param altitude: in km
    :param minElevation: in degrees
    """

    mapping = auromat.mapping.spacecraft.getMapping(imagePath,
                                                    fitsWcsPath,
                                                    photoTimeDelta,
                                                    tleFolder=tleFolder,
                                                    altitude=altitude)

    mapping = mapping.maskedByElevation(minElevation)
    mapping = auromat.resample.resample(mapping)

    tmpPath = tempfile.mktemp(suffix='.png')
    saveFig(tmpPath, auromat.draw.drawPlot(mapping))
    _openFile(tmpPath)
Esempio n. 2
0
 def _testMLatMLTPolarMapNorthPole(self):
     m = _getMappingNorth()
     m.checkGuarantees()
     #m = m.maskedByElevation(10)
     #m.checkGuarantees()
     m = resample(m, arcsecPerPx=100, method='mean')
     m.checkGuarantees()
     saveFig('test_mlatmlt_polar_north.png', drawMLatMLTPolar(m))
Esempio n. 3
0
 def _testConstellationPlot(self):
     imagePath = getResourcePath('ISS030-E-102170_dc.jpg')
     wcsPath = getResourcePath('ISS030-E-102170_dc.wcs')
     
     m = getMapping(imagePath, wcsPath)
     figax = loadFigImage(imagePath)
     drawConstellations(figax, wcsPath, clipPoly=outline(~m.intersectsEarth))
     saveFig('test_constellations.jpg', figax)
Esempio n. 4
0
 def testParallelsMeridiansPlot(self):
     imagePath = getResourcePath('ISS030-E-102170_dc.jpg')
     wcsPath = getResourcePath('ISS030-E-102170_dc.wcs')
     m = getMapping(imagePath, wcsPath, altitude=0, fastCenterCalculation=True)
     figax = loadFigImage(imagePath)
     drawParallelsAndMeridians(m, figax=figax)
     drawConstellations(figax, wcsPath, clipPoly=outline(~m.intersectsEarth))
     saveFig('test_parallelsmeridians.jpg', figax)
Esempio n. 5
0
 def _testMLatMLTPolarMapBothHemispheres(self):
     m = _getMappingSouth()
     m.checkGuarantees()
     #m = m.maskedByElevation(10)
     #m.checkGuarantees()
     m = resample(m, arcsecPerPx=100, method='mean')
     m.checkGuarantees()
     seqbb = BoundingBox(latSouth=-61.150846231, lonWest=142.622725698, latNorth=6.84984918353, lonEast=-116.820615123)
     saveFig('test_mlatmlt_polar_seqbb.png', drawMLatMLTPolar(m, boundingBox=seqbb))
Esempio n. 6
0
 def _testMiracle(self):
     m = _getMiracleMapping()
     saveFig('heat_intersection.png', drawHeatmap(m.intersectionInflatedCorner[...,0]))
     drawHeatmaps(m)
     m.checkGuarantees()
     m = m.maskedByElevation(10)
     m.checkGuarantees()
     m = resample(m, arcsecPerPx=100, method='mean')
     m.checkGuarantees()
     saveFig('test_stereo.png', drawStereographic(m))
Esempio n. 7
0
 def _testColors(self):
     m = _getMappingNorth()
     m = resample(m, arcsecPerPx=100, method='mean')
     saveFig('test_white.png', drawStereographic(m, bottomTitle='foo'), bgcolor='white')
     saveFig('test_black.png', drawStereographic(m, bottomTitle='foo'), bgcolor='black')
     saveFig('test_polar_white.png', drawMLatMLTPolar(m), bgcolor='white')
     saveFig('test_polar_black.png', drawMLatMLTPolar(m), bgcolor='black')
Esempio n. 8
0
def debugHorizon(imagePath, fitsWcsPath, tleFolder, photoTimeDelta=None, altitude=110):
    """
    Visualizes the horizon of the modelled earth and inflated earth (=aurora)
    for the given parameters.
    
    :param datetime.timedelta photoTimeDelta: amount to shift the image time (affects calculated
        camera position and therefore the geodetic coordinates)
    """    
    mapping = auromat.mapping.spacecraft.getMapping(imagePath, fitsWcsPath, photoTimeDelta,
                                                   tleFolder=tleFolder, altitude=altitude) 
    
    tmpPath = tempfile.mktemp(suffix='.jpg')
    saveFig(tmpPath, auromat.draw.drawHorizon(mapping))
    
    _openFile(tmpPath)
Esempio n. 9
0
 def _testHoleBug(self):
     """
     Triggers a (now fixed) bug that occured when 'mean' resampling led to
     single-polygon holes where surrounding polygons were well-defined.
     A hole is a polygon such that all corners are defined and just the polygon
     center data was missing (color etc.). The issue was that those holes were
     not filtered and led to subsequent errors. The fix was to filter not by whether
     all corners are defined but whether the color is defined as this also guarantees
     that the corners are defined.        
     """
     m = _getMappingNorth()
     m = resample(m, arcsecPerPx=200, method='mean')
     # saving as svg without rasterization will lead to errors when trying to use
     # polygons with NaN colors; saving as png only leads to black areas!
     saveFig('test_stereo.svg', drawStereographic(m, rasterized=False))
Esempio n. 10
0
 def _testParallelsMeridiansPlotOptimized(self):
     imagePath = getResourcePath('ISS030-E-102170_dc.jpg')
     wcsPath = getResourcePath('ISS030-E-102170_dc.wcs')
     # As we precalculated the bounding box and the lat/lon label position
     # we only need to access the 'latCenter', 'lonCenter' and 'intersectsEarth'
     # attributes of the spacecraft mapping. This means that we don't need
     # any sanitization applied on the corner coordinate arrays ('lats','lons').
     # For this reason, and because we don't use masking, we set nosanitize=True
     # and can cut the required time in half. 
     m = getMapping(imagePath, wcsPath, altitude=0, fastCenterCalculation=False, nosanitize=True)
     
     # the following values must be precalculated to use the optimization
     # the bounding box at altitude=0 without any masking
     bb = BoundingBox(latSouth=49.3401757697, lonWest=-116.368770925, latNorth=64.288454984, lonEast=-91.8890098192)
     # center of bounding box at altitude=0 when masked below 10deg elevation
     labelLat, labelLon = 53.133, -98.684
     
     figax = loadFigImage(imagePath)
     drawParallelsAndMeridians(figax, m, boundingBox=bb, labelLat=labelLat, labelLon=labelLon)
     drawConstellations(figax, wcsPath, clipPoly=outline(~m.intersectsEarth))
     saveFig('test_parallelsmeridians_optimized.jpg', figax)
Esempio n. 11
0
def debugHorizon(imagePath,
                 fitsWcsPath,
                 tleFolder,
                 photoTimeDelta=None,
                 altitude=110):
    """
    Visualizes the horizon of the modelled earth and inflated earth (=aurora)
    for the given parameters.
    
    :param datetime.timedelta photoTimeDelta: amount to shift the image time (affects calculated
        camera position and therefore the geodetic coordinates)
    """
    mapping = auromat.mapping.spacecraft.getMapping(imagePath,
                                                    fitsWcsPath,
                                                    photoTimeDelta,
                                                    tleFolder=tleFolder,
                                                    altitude=altitude)

    tmpPath = tempfile.mktemp(suffix='.jpg')
    saveFig(tmpPath, auromat.draw.drawHorizon(mapping))

    _openFile(tmpPath)
Esempio n. 12
0
def debugPlot(imagePath, fitsWcsPath, tleFolder, photoTimeDelta=None, altitude=0, minElevation=10):
    """
    Plot the georeferenced image on a map. This allows to play with the image timestamp
    and mapping altitude.
    
    :param imagePath:
    :param fitsWcsPath:
    :param tleFolder:
    :param datetime.timedelta photoTimeDelta: amount to shift the image time (affects calculated
        camera position and therefore the geodetic coordinates)
    :param altitude: in km
    :param minElevation: in degrees
    """
     
    mapping = auromat.mapping.spacecraft.getMapping(imagePath, fitsWcsPath, photoTimeDelta, 
                                                   tleFolder=tleFolder, altitude=altitude)
    
    mapping = mapping.maskedByElevation(minElevation)
    mapping = auromat.resample.resample(mapping)
        
    tmpPath = tempfile.mktemp(suffix='.png')
    saveFig(tmpPath, auromat.draw.drawPlot(mapping))
    _openFile(tmpPath)    
Esempio n. 13
0
def maskStarfield(imagePath, channel=None, blackenLowerPart=True, ignoreVeryDark=True,
                  debugPathPrefix=None, debugJpegQuality=80):
    """
    Automatic masking of the starfield in the given image using
    a combination of image processing and object detection steps.
    
    :param str channel: the channel to use for analysis
        'R','G','B', or None for combining all channels into a grayscale image
    :param bool blackenLowerPart: If the earth is in the lower part of the image
                             then this should be set to True as it will
                             broadly mask parts of the earth not detected otherwise.
    :param bool ignoreVeryDark: If True, then areas (block) which are almost totally black
                           are not considered as starfield. This is sometimes useful
                           to ignore very dark spacecraft structures which would later
                           on be detected as stars.
    :param str debugPathPrefix: if given, the folder in which to store debug images
                                illustrating the different processing stages
    :param int debugJpegQuality: JPEG quality from 0 to 100 used for storing debug images;
                                 only contour images are currently saved as JPEG
    :rtype: tuple (mask, sigma)
    """    
    if debugPathPrefix:
        red = (0,0,255)
        green = (0,255,0)
        orange = (0,106,255)

        debugHistogramPath = debugPathPrefix + 'hist.svg'
        debugThresholdedImagePath = debugPathPrefix + 'thresh.png'
        debugContoursImagePath = debugPathPrefix + 'cont.jpg'
        debugContoursMaskImagePath = debugPathPrefix + 'cont_mask.jpg'
        debugAdaptiveThresholdedImagePath = debugPathPrefix + 'thresh_adapt.png'
        debugCutoffImagePath = debugPathPrefix + 'cutoff.jpg'
    
    if isinstance(imagePath, np.ndarray):
        # assume RGB image array
        im = np.require(imagePath, np.uint8, 'C')
        im = cv.cvtColor(im, cv.COLOR_RGB2BGR)
        imagePath = '[array]'
    else:
        im = cv.imread(imagePath)
    if channel is None:
        imgray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
    elif channel.lower() == 'r':
        imgray = im[:,:,2]
    elif channel.lower() == 'g':
        imgray = im[:,:,1]
    elif channel.lower() == 'b':
        imgray = im[:,:,0]
    else:
        raise ValueError('channel is "{}" but must be R,G,B or None'.format(channel))
    
    # opencv requires a contiguous array..
    imgray = np.require(imgray, np.uint8, 'C')
    
    # Step 1: Find dark areas which might be starfield
    
    fudge = 20
    binary, hist, threshold, firstSpike = _binarizeStarfieldImage(imgray, fudge=fudge)
    contours, area, isBigContour, isSmallLongContour, isSmallShortContour = _findAndCategorizeContours(binary)
    mask = _createStarfieldMask(im, contours, area, isBigContour, None, blackenLowerPart)
    starfieldAreaRatio = np.sum(mask) / (mask.shape[0]*mask.shape[1])
        
    while starfieldAreaRatio < 0.1:
        # A part other then the starfield was probably picked as reference threshold because it was darker.
        # Remember that the first spike in the histogram (=darkest part) is used to determine the threshold.
        # To fix this situation, we just raise the threshold and hope for the best.
        print('Starfield area is only ' + "{0:.2f}".format(starfieldAreaRatio*100) +\
              '% (< 10%). Trying a higher threshold. ' +\
              '(' + os.path.basename(imagePath) + ')')
        fudge += 20
        binary, hist, threshold, firstSpike = _binarizeStarfieldImage(imgray, fudge=fudge)
        contours, area, isBigContour, isSmallLongContour, isSmallShortContour = _findAndCategorizeContours(binary)
        # FIXME use small long contours as well for masking, why did we disable that?
        mask = _createStarfieldMask(im, contours, area, isBigContour, None, blackenLowerPart)
        
        starfieldAreaRatio = np.sum(mask) / (mask.shape[0]*mask.shape[1])
        if starfieldAreaRatio >= 0.1:
            print('Starfield area is now ' + "{0:.2f}".format(starfieldAreaRatio*100) + '%')
        elif fudge > 100:
            print('giving up')
            break
        
    if debugPathPrefix and debugHistogramPath:
        vlines = [(firstSpike, 'red'), (threshold, 'blue')]
        try:
            saveFig(debugHistogramPath, drawHistogram(hist, vlines, 
                                                      xlabel='Intensity', 
                                                      ylabel='Pixel Count',
                                                      linecolor='black'))
        except:
            ex = traceback.format_exc()
            with open(debugPathPrefix + 'matplotlib.EXCEPTION', 'w') as fp:
                fp.write(ex)
        
    if debugPathPrefix and debugThresholdedImagePath:
        cv.imwrite(debugThresholdedImagePath, binary, [IMWRITE_PNG_COMPRESSION, 9])
        
    if debugPathPrefix and debugContoursImagePath:
        imContours = im.copy()
        cv.drawContours(imContours,contours[isBigContour],-1,red,2)
        cv.drawContours(imContours,contours[isSmallLongContour],-1,orange,2)
        cv.drawContours(imContours,contours[isSmallShortContour],-1,green,2)
        cv.imwrite(debugContoursImagePath, imContours, [IMWRITE_JPEG_QUALITY, debugJpegQuality])
        del imContours

    if debugPathPrefix and debugContoursMaskImagePath:
        # draw the borders of the current mask onto the original image
        imContoursMask = im.copy()
        res = _findAndCategorizeContours(mask)
        contours = res[0]
        cv.drawContours(imContoursMask,contours,-1,(255,255,255),3)
        cv.imwrite(debugContoursMaskImagePath, imContoursMask, [IMWRITE_JPEG_QUALITY, debugJpegQuality])
        del imContoursMask

    imgray[~mask] = 0
    
    # Step 2: Filter out dark areas which are probably not starfield
    
    # Step 2a: try to find lines and mask blocks containing them
    binary = _masked_adaptive_threshold(imgray, mask, 255, 89, -1)
    if debugPathPrefix and debugAdaptiveThresholdedImagePath:
        binaryC = cv.cvtColor(binary, cv.COLOR_GRAY2BGR)

    binary = cv.medianBlur(binary, 3)
    lines = cv.HoughLinesP(binary.copy(), 1, pi/180, 200, minLineLength=100, maxLineGap=4)
    
    blockShape = _getBlockShape(im)
    blockH, blockW = blockShape
    blockViewMask = view_as_blocks(mask, blockShape)
    
    if lines is not None:        
        # draw all lines on a blank binary image
        # then for each block check if it contains part of a line
        imFilledOffenders = np.zeros(mask.shape, np.uint8)
        
        for line in lines[0,:]:
            cv.line(imFilledOffenders, (line[0], line[1]), (line[2], line[3]), 255)
            
            if debugPathPrefix and debugAdaptiveThresholdedImagePath:
                cv.line(binaryC, (line[0], line[1]), (line[2], line[3]), red, 5)

        blockViewOffenders = view_as_blocks(imFilledOffenders, blockShape)
    
        isBlockContainingOffenders = (blockViewOffenders==255).any(axis=-1).any(axis=-1)
        blockViewMask[isBlockContainingOffenders] = False
        
    if debugPathPrefix and debugAdaptiveThresholdedImagePath:
        cv.imwrite(debugAdaptiveThresholdedImagePath, binaryC, [IMWRITE_PNG_COMPRESSION, 9])
       
    # Step 2b: make very dark pixels black and mask all-black blocks
    if ignoreVeryDark:
        if debugPathPrefix and debugCutoffImagePath:
            wasStarfieldBlock = blockViewMask.all(axis=-1).all(axis=-1)
        
        imgrayCutoff = imgray.copy()
        # blurring will wash out very tiny artifacts (which could also be faint small stars)
        # this helps here because we require that absolutely all of a block must be black
        imgrayCutoff = cv.blur(imgrayCutoff, (3,3))
        cutoffThreshold = max(30, firstSpike + 20)
        print('cutoffThreshold:', cutoffThreshold, os.path.basename(imagePath))
        imgrayCutoff[imgrayCutoff<cutoffThreshold] = 0
    
        blockViewCutoff = view_as_blocks(imgrayCutoff, blockShape)
        isBlockPureBlack = (blockViewCutoff==0).all(axis=-1).all(axis=-1)
        
        if debugPathPrefix and debugCutoffImagePath:
            imCutoff = im.copy()
            imCutoff[~mask] = 0
            
            blockViewCutoffC = view_as_blocks(imCutoff, (blockH,blockW,3))
            blockGotMasked = np.logical_and(wasStarfieldBlock, isBlockPureBlack)
            # draw rectangle around each block that was masked
            blockViewCutoffC[blockGotMasked,0,:4,:] = red
            blockViewCutoffC[blockGotMasked,0,-4:,:] = red
            blockViewCutoffC[blockGotMasked,0,:,:4] = red
            blockViewCutoffC[blockGotMasked,0,:,-4:] = red
            cv.imwrite(debugCutoffImagePath, imCutoff, [IMWRITE_JPEG_QUALITY, debugJpegQuality])
            del imCutoff
        
        blockViewMask[isBlockPureBlack] = False
        
    # Step 3: Filter out lonely starfield blocks (surrounded by non-starfield blocks)
    isStarfieldBlock = blockViewMask.all(axis=-1).all(axis=-1)
    
    neighborCountKernel = np.ones((3,3), dtype=int)
    neighborCountKernel[1,1] = 0
    neighbors = convolve2d(isStarfieldBlock.astype(int), neighborCountKernel, mode='same')
    isLonelyBlock = np.logical_and(isStarfieldBlock, neighbors == 0)
    blockViewMask[isLonelyBlock] = False
       
    # estimate noise level using the biggest starfield rectangle we got
    (rectY,rectX), (rectH,rectW) = _max_size_rectangle(isStarfieldBlock, value=True)
    rectY, rectH = rectY*blockH, rectH*blockH
    rectX, rectW = rectX*blockW, rectW*blockW
    imgrayBiggestRect = imgray[rectY:rectY+rectH, rectX:rectX+rectW]
    sigma = _estimateNoiseLevel(imgrayBiggestRect)
    print('Sigma:', sigma)
    if debugPathPrefix:
        with open(os.path.join(debugPathPrefix + '.sigma'), 'w') as fp:
            fp.write(str(sigma))

    return mask, sigma
Esempio n. 14
0
 def _testStereographicMap(self):
     m = _getMappingSouth()
     m = m.maskedByElevation(10)
     m = resample(m, arcsecPerPx=100, method='mean')
     saveFig('test_stereo.svg', drawStereographic(m), dpi=200)
Esempio n. 15
0
 def _testBBPole2(self):
     bb = BoundingBox(latSouth=35.3446724767, lonWest=-180.0, latNorth=90.0, lonEast=180.0)
     m = _getMappingNorth()
     m = resample(m, arcsecPerPx=100, method='mean')
     saveFig('test_bb.png', drawStereographic(m, boundingBox=bb))
Esempio n. 16
0
	lats = masked.lats
	lons = masked.lons

	# plt.scatter(lats, lons, np.array(masked.img).flatten())
	# plt.show()
	# for i in range(0, len(lats)):
	# 	#print(lats[i])
	# 	if lats[i] != lats[i] or lons[i] != lons[i]:
	# 		del lats[i]
	# 		del lons[i]
	# 		del img[i:i+3]
	# 	# else:
	# 	# 	print(lats[i])

	# print(len(img))
	# print(len(lats))
	# print(len(lons))

	# f = open('/home/lianqiang/data/img'+number, 'a', 1000)
	# f.write(str(img))
	# f.close()
	# f = open('/home/lianqiang/data/lats'+number, 'a', 1000)
	# f.write(str(lats))
	# f.close()
	# f = open('/home/lianqiang/data/lons'+number, 'a', 1000)
	# f.write(str(lons))
	# f.close()

	saveFig('/home/lianqiang/data/map_test.png', draw.drawPlot(masked))
	#saveFig('/home/lianqiang/data/map.png', draw.drawStereographic(masked, lineDelta=2, width=1600, height=1000,))
	#saveFig('/home/lianqiang/data/astrometry.jpg', draw.drawReferenceStars(mapping, scale=2))
Esempio n. 17
0
 def _testSingle(self):
     provider = ISSMappingProvider(url, cacheFolder, altitude=110)
     
     mapping = provider.get(datetime(2012,1,25,9,26,57))
     mapping = resample(mapping, arcsecPerPx=100)
     saveFig('test.png', drawStereographicMLatMLT(mapping))
Esempio n. 18
0
def maskStarfield(imagePath,
                  channel=None,
                  blackenLowerPart=True,
                  ignoreVeryDark=True,
                  debugPathPrefix=None,
                  debugJpegQuality=80):
    """
    Automatic masking of the starfield in the given image using
    a combination of image processing and object detection steps.
    
    :param str channel: the channel to use for analysis
        'R','G','B', or None for combining all channels into a grayscale image
    :param bool blackenLowerPart: If the earth is in the lower part of the image
                             then this should be set to True as it will
                             broadly mask parts of the earth not detected otherwise.
    :param bool ignoreVeryDark: If True, then areas (block) which are almost totally black
                           are not considered as starfield. This is sometimes useful
                           to ignore very dark spacecraft structures which would later
                           on be detected as stars.
    :param str debugPathPrefix: if given, the folder in which to store debug images
                                illustrating the different processing stages
    :param int debugJpegQuality: JPEG quality from 0 to 100 used for storing debug images;
                                 only contour images are currently saved as JPEG
    :rtype: tuple (mask, sigma)
    """
    if debugPathPrefix:
        red = (0, 0, 255)
        green = (0, 255, 0)
        orange = (0, 106, 255)

        debugHistogramPath = debugPathPrefix + 'hist.svg'
        debugThresholdedImagePath = debugPathPrefix + 'thresh.png'
        debugContoursImagePath = debugPathPrefix + 'cont.jpg'
        debugContoursMaskImagePath = debugPathPrefix + 'cont_mask.jpg'
        debugAdaptiveThresholdedImagePath = debugPathPrefix + 'thresh_adapt.png'
        debugCutoffImagePath = debugPathPrefix + 'cutoff.jpg'

    if isinstance(imagePath, np.ndarray):
        # assume RGB image array
        im = np.require(imagePath, np.uint8, 'C')
        im = cv.cvtColor(im, cv.COLOR_RGB2BGR)
        imagePath = '[array]'
    else:
        im = cv.imread(imagePath)
    if channel is None:
        imgray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
    elif channel.lower() == 'r':
        imgray = im[:, :, 2]
    elif channel.lower() == 'g':
        imgray = im[:, :, 1]
    elif channel.lower() == 'b':
        imgray = im[:, :, 0]
    else:
        raise ValueError(
            'channel is "{}" but must be R,G,B or None'.format(channel))

    # opencv requires a contiguous array..
    imgray = np.require(imgray, np.uint8, 'C')

    # Step 1: Find dark areas which might be starfield

    fudge = 20
    binary, hist, threshold, firstSpike = _binarizeStarfieldImage(imgray,
                                                                  fudge=fudge)
    contours, area, isBigContour, isSmallLongContour, isSmallShortContour = _findAndCategorizeContours(
        binary)
    mask = _createStarfieldMask(im, contours, area, isBigContour, None,
                                blackenLowerPart)
    starfieldAreaRatio = np.sum(mask) / (mask.shape[0] * mask.shape[1])

    while starfieldAreaRatio < 0.1:
        # A part other then the starfield was probably picked as reference threshold because it was darker.
        # Remember that the first spike in the histogram (=darkest part) is used to determine the threshold.
        # To fix this situation, we just raise the threshold and hope for the best.
        print('Starfield area is only ' + "{0:.2f}".format(starfieldAreaRatio*100) +\
              '% (< 10%). Trying a higher threshold. ' +\
              '(' + os.path.basename(imagePath) + ')')
        fudge += 20
        binary, hist, threshold, firstSpike = _binarizeStarfieldImage(
            imgray, fudge=fudge)
        contours, area, isBigContour, isSmallLongContour, isSmallShortContour = _findAndCategorizeContours(
            binary)
        # FIXME use small long contours as well for masking, why did we disable that?
        mask = _createStarfieldMask(im, contours, area, isBigContour, None,
                                    blackenLowerPart)

        starfieldAreaRatio = np.sum(mask) / (mask.shape[0] * mask.shape[1])
        if starfieldAreaRatio >= 0.1:
            print('Starfield area is now ' +
                  "{0:.2f}".format(starfieldAreaRatio * 100) + '%')
        elif fudge > 100:
            print('giving up')
            break

    if debugPathPrefix and debugHistogramPath:
        vlines = [(firstSpike, 'red'), (threshold, 'blue')]
        try:
            saveFig(
                debugHistogramPath,
                drawHistogram(hist,
                              vlines,
                              xlabel='Intensity',
                              ylabel='Pixel Count',
                              linecolor='black'))
        except:
            ex = traceback.format_exc()
            with open(debugPathPrefix + 'matplotlib.EXCEPTION', 'w') as fp:
                fp.write(ex)

    if debugPathPrefix and debugThresholdedImagePath:
        cv.imwrite(debugThresholdedImagePath, binary,
                   [IMWRITE_PNG_COMPRESSION, 9])

    if debugPathPrefix and debugContoursImagePath:
        imContours = im.copy()
        cv.drawContours(imContours, contours[isBigContour], -1, red, 2)
        cv.drawContours(imContours, contours[isSmallLongContour], -1, orange,
                        2)
        cv.drawContours(imContours, contours[isSmallShortContour], -1, green,
                        2)
        cv.imwrite(debugContoursImagePath, imContours,
                   [IMWRITE_JPEG_QUALITY, debugJpegQuality])
        del imContours

    if debugPathPrefix and debugContoursMaskImagePath:
        # draw the borders of the current mask onto the original image
        imContoursMask = im.copy()
        res = _findAndCategorizeContours(mask)
        contours = res[0]
        cv.drawContours(imContoursMask, contours, -1, (255, 255, 255), 3)
        cv.imwrite(debugContoursMaskImagePath, imContoursMask,
                   [IMWRITE_JPEG_QUALITY, debugJpegQuality])
        del imContoursMask

    imgray[~mask] = 0

    # Step 2: Filter out dark areas which are probably not starfield

    # Step 2a: try to find lines and mask blocks containing them
    binary = _masked_adaptive_threshold(imgray, mask, 255, 89, -1)
    if debugPathPrefix and debugAdaptiveThresholdedImagePath:
        binaryC = cv.cvtColor(binary, cv.COLOR_GRAY2BGR)

    binary = cv.medianBlur(binary, 3)
    lines = cv.HoughLinesP(binary.copy(),
                           1,
                           pi / 180,
                           200,
                           minLineLength=100,
                           maxLineGap=4)

    blockShape = _getBlockShape(im)
    blockH, blockW = blockShape
    blockViewMask = view_as_blocks(mask, blockShape)

    if lines is not None:
        # draw all lines on a blank binary image
        # then for each block check if it contains part of a line
        imFilledOffenders = np.zeros(mask.shape, np.uint8)

        for line in lines[0, :]:
            cv.line(imFilledOffenders, (line[0], line[1]), (line[2], line[3]),
                    255)

            if debugPathPrefix and debugAdaptiveThresholdedImagePath:
                cv.line(binaryC, (line[0], line[1]), (line[2], line[3]), red,
                        5)

        blockViewOffenders = view_as_blocks(imFilledOffenders, blockShape)

        isBlockContainingOffenders = (blockViewOffenders == 255).any(
            axis=-1).any(axis=-1)
        blockViewMask[isBlockContainingOffenders] = False

    if debugPathPrefix and debugAdaptiveThresholdedImagePath:
        cv.imwrite(debugAdaptiveThresholdedImagePath, binaryC,
                   [IMWRITE_PNG_COMPRESSION, 9])

    # Step 2b: make very dark pixels black and mask all-black blocks
    if ignoreVeryDark:
        if debugPathPrefix and debugCutoffImagePath:
            wasStarfieldBlock = blockViewMask.all(axis=-1).all(axis=-1)

        imgrayCutoff = imgray.copy()
        # blurring will wash out very tiny artifacts (which could also be faint small stars)
        # this helps here because we require that absolutely all of a block must be black
        imgrayCutoff = cv.blur(imgrayCutoff, (3, 3))
        cutoffThreshold = max(30, firstSpike + 20)
        print('cutoffThreshold:', cutoffThreshold, os.path.basename(imagePath))
        imgrayCutoff[imgrayCutoff < cutoffThreshold] = 0

        blockViewCutoff = view_as_blocks(imgrayCutoff, blockShape)
        isBlockPureBlack = (blockViewCutoff == 0).all(axis=-1).all(axis=-1)

        if debugPathPrefix and debugCutoffImagePath:
            imCutoff = im.copy()
            imCutoff[~mask] = 0

            blockViewCutoffC = view_as_blocks(imCutoff, (blockH, blockW, 3))
            blockGotMasked = np.logical_and(wasStarfieldBlock,
                                            isBlockPureBlack)
            # draw rectangle around each block that was masked
            blockViewCutoffC[blockGotMasked, 0, :4, :] = red
            blockViewCutoffC[blockGotMasked, 0, -4:, :] = red
            blockViewCutoffC[blockGotMasked, 0, :, :4] = red
            blockViewCutoffC[blockGotMasked, 0, :, -4:] = red
            cv.imwrite(debugCutoffImagePath, imCutoff,
                       [IMWRITE_JPEG_QUALITY, debugJpegQuality])
            del imCutoff

        blockViewMask[isBlockPureBlack] = False

    # Step 3: Filter out lonely starfield blocks (surrounded by non-starfield blocks)
    isStarfieldBlock = blockViewMask.all(axis=-1).all(axis=-1)

    neighborCountKernel = np.ones((3, 3), dtype=int)
    neighborCountKernel[1, 1] = 0
    neighbors = convolve2d(isStarfieldBlock.astype(int),
                           neighborCountKernel,
                           mode='same')
    isLonelyBlock = np.logical_and(isStarfieldBlock, neighbors == 0)
    blockViewMask[isLonelyBlock] = False

    # estimate noise level using the biggest starfield rectangle we got
    (rectY, rectX), (rectH, rectW) = _max_size_rectangle(isStarfieldBlock,
                                                         value=True)
    rectY, rectH = rectY * blockH, rectH * blockH
    rectX, rectW = rectX * blockW, rectW * blockW
    imgrayBiggestRect = imgray[rectY:rectY + rectH, rectX:rectX + rectW]
    sigma = _estimateNoiseLevel(imgrayBiggestRect)
    print('Sigma:', sigma)
    if debugPathPrefix:
        with open(os.path.join(debugPathPrefix + '.sigma'), 'w') as fp:
            fp.write(str(sigma))

    return mask, sigma
Esempio n. 19
0
 def testIndxPlot(self):
     imagePath = getResourcePath('ISS030-E-102170_dc.jpg')
     wcsPath = getResourcePath('ISS030-E-102170_dc.wcs')
     figax = drawIndxPlot(imagePath, wcsPath=wcsPath, useWebCatalog=True, webCatalogLimit=200)
     saveFig('test_indx.png', figax)
Esempio n. 20
0
 def _testHorizonImage(self):
     m = _getMappingNorth()
     saveFig('horizon.jpg', drawHorizon(m))
Esempio n. 21
0
    lats = masked.lats
    lons = masked.lons

    # plt.scatter(lats, lons, np.array(masked.img).flatten())
    # plt.show()
    # for i in range(0, len(lats)):
    # 	#print(lats[i])
    # 	if lats[i] != lats[i] or lons[i] != lons[i]:
    # 		del lats[i]
    # 		del lons[i]
    # 		del img[i:i+3]
    # 	# else:
    # 	# 	print(lats[i])

    # print(len(img))
    # print(len(lats))
    # print(len(lons))

    # f = open('/home/lianqiang/data/img'+number, 'a', 1000)
    # f.write(str(img))
    # f.close()
    # f = open('/home/lianqiang/data/lats'+number, 'a', 1000)
    # f.write(str(lats))
    # f.close()
    # f = open('/home/lianqiang/data/lons'+number, 'a', 1000)
    # f.write(str(lons))
    # f.close()

    saveFig('/home/lianqiang/data/map_test.png', draw.drawPlot(masked))
    #saveFig('/home/lianqiang/data/map.png', draw.drawStereographic(masked, lineDelta=2, width=1600, height=1000,))
    #saveFig('/home/lianqiang/data/astrometry.jpg', draw.drawReferenceStars(mapping, scale=2))