def __call__(self, context, *args): LOG.info(self.mess) tsi = args[0] self.image = tsi.pixels meanIntensity = np.mean(self.image) if meanIntensity < self.minIntensity: # FIXME: this should be handled with an error. LOG.warn('Image is too dark, skiping colorcard detection!') return([self.image, [None, None, None]]) if not self.useWhiteBackground: self.imagePyramid = cd.createImagePyramid(self.image) ccdImg = cv2.imread(self.ccf)[:, :, ::-1] if ccdImg is None: raise ValueError("Failed to read %s" % self.ccf) self.colorcardPyramid = cd.createImagePyramid(ccdImg) # create image pyramid for multiscale matching SearchRange = [self.colorcardPyramid[0].shape[1], self.colorcardPyramid[0].shape[0]] score, loc, angle = cd.matchTemplatePyramid( self.imagePyramid, self.colorcardPyramid, 0, EstimatedLocation=self.colorcardPosition, SearchRange=SearchRange ) if score > 0.3: # extract color information self.foundCard = self.image[ loc[1] - ccdImg.shape[0] // 2:loc[1] + ccdImg.shape[0] // 2, loc[0] - ccdImg.shape[1] // 2:loc[0] + ccdImg.shape[1] // 2] self.ccdColors, _ = cd.getColorcardColors(self.foundCard, GridSize=[6, 4]) self.colorcardParams = cd.estimateColorParameters( self.colorcardTrueColors, self.colorcardColors ) # Save colourcard image to instance self.colorcardImage = ccdImg # for displaying self.loc = loc else: # FIXME: this should be handled with an error. LOG.warn('Cannot find color card') self.colorcardParams = [None, None, None] else: self.colorcardParams = cd.estimateColorParametersFromWhiteBackground( self.image, self.backgroundWindow, self.maxIntensity) return([tsi, self.colorcardParams])
def __call__(self, context, *args): LOG.info(self.mess) tsi = args[0] self.image = tsi.pixels temp = np.zeros_like(self.image) temp[:, :, :] = self.image[:, :, :] temp[:, :, 1] = 0 # suppress green channel self.imagePyramid = cd.createImagePyramid(temp) self.trayPyramids = [] for i in range(self.trayNumber): # fixed tray image so that perspective postions of the trays are # fixed trayFile = os.path.join(context.ints.path, self.settingPath, self.trayFiles % i) trayImage = cv2.imread(trayFile)[:, :, ::-1] if trayImage is None: LOG.error("Fail to read", trayFile) trayImage[:, :, 1] = 0 # suppress green channel trayPyramid = cd.createImagePyramid(trayImage) self.trayPyramids.append(trayPyramid) self.trayLocs = [] for i, trayPyramid in enumerate(self.trayPyramids): SearchRange = [trayPyramid[0].shape[1] // 6, trayPyramid[0].shape[0] // 6] score, loc, angle = cd.matchTemplatePyramid( self.imagePyramid, trayPyramid, RotationAngle=0, EstimatedLocation=self.trayPositions[i], SearchRange=SearchRange) if score < 0.3: # FIXME: For now we don't handle missing trays. raise PCExBrakeInPipeline( self.actName, "Low tray matching score. Likely tray %d is missing." % i) self.trayLocs.append(loc) # add tray location information context.outputwithimage["trayLocs"] = self.trayLocs tsi.pixels = self.image return([tsi, self.imagePyramid, self.trayLocs])
def __exec__(self, context, *args): tsi = args[0] self.image = tsi.pixels temp = np.zeros_like(self.image) temp[:, :, :] = self.image[:, :, :] temp[:, :, 1] = 0 # suppress green channel self.imagePyramid = cd.createImagePyramid(temp) self.trayPyramids = [] for i in range(self.trayNumber): # fixed tray image so that perspective postions of the trays are # fixed trayFile = os.path.join(context.ints.path, self.settingPath, self.trayFiles % i) trayImage = read_image(trayFile) if trayImage is None: LOG.error("Fail to read", trayFile) trayImage[:, :, 1] = 0 # suppress green channel trayImage = trayImage[:, :, 0:3] # supress Alpha channel trayPyramid = cd.createImagePyramid(trayImage) self.trayPyramids.append(trayPyramid) self.trayLocs = [] for i, trayPyramid in enumerate(self.trayPyramids): SearchRange = [trayPyramid[0].shape[1] // 6, trayPyramid[0].shape[0] // 6] score, loc, angle = cd.matchTemplatePyramid( self.imagePyramid, trayPyramid, RotationAngle=0, EstimatedLocation=self.trayPositions[i], SearchRange=SearchRange) if score < 0.3: raise PCExCannotFindTray(i, tsi.path) self.trayLocs.append(loc) tsi.pixels = self.image return([tsi, self.imagePyramid, self.trayLocs])
def __exec__(self, context, *args): tsi = args[0] self.image = tsi.pixels meanIntensity = np.mean(self.image) if meanIntensity < self.minIntensity: raise PCExImageTooDark(tsi.path) if not self.useWhiteBackground: self.imagePyramid = cd.createImagePyramid(self.image) ccdImg = read_image(self.ccf)[:, :, 0:3] if ccdImg is None: raise PCExBadImage(self.ccf) self.ccdPyramid = cd.createImagePyramid(ccdImg) # create image pyramid for multiscale matching SearchRange = [self.ccdPyramid[0].shape[1] * 1.5, self.ccdPyramid[0].shape[0] * 1.5] score, loc, angle = cd.matchTemplatePyramid( self.imagePyramid, self.ccdPyramid, 0, EstimatedLocation=self.colorcardPosition, SearchRange=SearchRange) if score > 0.3: # extract color information self.foundCard = self.image[ loc[1] - ccdImg.shape[0] // 2:loc[1] + ccdImg.shape[0] // 2, loc[0] - ccdImg.shape[1] // 2:loc[0] + ccdImg.shape[1] // 2] self.ccdColors, _ = cd.getColorcardColors(self.foundCard, GridSize=[6, 4]) self.ccdParams = cd.estimateColorParameters( self.colorcardTrueColors, self.ccdColors) # Save colourcard image to instance self.colorcardImage = ccdImg # for displaying self.loc = loc else: raise PCExCannotFindColorCard(tsi.path) else: self.ccdParams = cd.estimateColorParametersFromWhiteBackground( self.image, self.backgroundWindow, self.maxIntensity) return([tsi, self.ccdParams])
def __call__(self, context, *args): LOG.info(self.mess) tsi, self.imagePyramid, self.trayLocs = args self.image = tsi.pixels # read pot template image and scale to the pot size potFile = os.path.join( context.ints.path, self.settingPath, self.potFile) potImage = cv2.imread(potFile)[:, :, ::-1] potTemplateFile = os.path.join( context.ints.path, self.settingPath, self.potTemplateFile) potTemplateImage = cv2.imread(potTemplateFile)[:, :, ::-1] potTemplateImage[:, :, 1] = 0 # suppress green channel potTemplateImage = cv2.resize( potTemplateImage.astype(np.uint8), (potImage.shape[1], potImage.shape[0])) self.potPyramid = cd.createImagePyramid(potTemplateImage) XSteps = self.traySize[0] // self.potSize[0] YSteps = self.traySize[1] // self.potSize[1] StepX = self.traySize[0] // XSteps StepY = self.traySize[1] // YSteps self.potLocs2 = [] self.potLocs2_ = [] potGridSize = [4, 5] for trayLoc in self.trayLocs: if trayLoc is None: self.potLocs2.append(None) continue StartX = trayLoc[0] - self.traySize[0] // 2 + StepX // 2 StartY = trayLoc[1] + self.traySize[1] // 2 - StepY // 2 SearchRange = [self.potPyramid[0].shape[1] // 4, self.potPyramid[0].shape[0] // 4] # SearchRange = [32, 32] locX = np.zeros(potGridSize) locY = np.zeros(potGridSize) for k in range(potGridSize[0]): for l in range(potGridSize[1]): estimateLoc = [StartX + StepX * k, StartY - StepY * l] score, loc, angle = cd.matchTemplatePyramid( self.imagePyramid, self.potPyramid, RotationAngle=0, EstimatedLocation=estimateLoc, NoLevels=3, SearchRange=SearchRange) locX[k, l], locY[k, l] = loc # correct for detection error potLocs = [] potLocs_ = [] diffXX = locX[1:, :] - locX[:-1, :] diffXY = locX[:, 1:] - locX[:, :-1] diffYX = locY[1:, :] - locY[:-1, :] diffYY = locY[:, 1:] - locY[:, :-1] diffXXMedian = np.median(diffXX) diffXYMedian = np.median(diffXY) diffYXMedian = np.median(diffYX) diffYYMedian = np.median(diffYY) for k in range(potGridSize[0]): for l in range(potGridSize[1]): locX[k, l] = trayLoc[0] + diffXXMedian * (k - (potGridSize[0] - 1.0) / 2.0) + \ diffXYMedian * (l - (potGridSize[1] - 1.0) / 2.0) locY[k, l] = trayLoc[1] + diffYXMedian * (k - (potGridSize[0] - 1.0) / 2.0) + \ diffYYMedian * (l - (potGridSize[1] - 1.0) / 2.0) # this fixes perpective shift # TODO: need a more elegant solution locY[k, l] = locY[k, l] + 10 potLocs.append([locX[k, l], locY[k, l]]) potLocs_.append(estimateLoc) self.potLocs2.append(potLocs) self.potLocs2_.append(potLocs_) # Create a new ImagePotMatrix with newly discovered locations ipmPrev = None if context.hasSubSecName("ipmPrev"): ipmPrev = context.ipmPrev flattened = list(chain.from_iterable(self.potLocs2)) growM = round(min(spatial.distance.pdist(flattened)) / 2) tsi.ipm = tm_pot.ImagePotMatrix( tsi, pots=[], growM=growM, ipmPrev=ipmPrev) potID = 1 for tray in self.potLocs2: trayID = 1 for center in tray: r = tm_pot.ImagePotRectangle( center, tsi.pixels.shape, growM=growM) p = tm_pot.ImagePotHandler(potID, r, tsi.ipm) p.setMetaId("trayID", trayID) tsi.ipm.addPot(p) potID += 1 trayID += 1 context.outputwithimage["potLocs"] = self.potLocs2 return([tsi])
def __exec__(self, context, *args): tsi, self.imagePyramid, self.trayLocs = args self.image = tsi.pixels # read pot template image and scale to the pot size potFile = os.path.join( context.ints.path, self.settingPath, self.potFile) potImage = read_image(potFile) potTemplateFile = os.path.join( context.ints.path, self.settingPath, self.potTemplateFile) potTemplateImage = read_image(potTemplateFile) potTemplateImage[:, :, 1] = 0 # suppress green channel potTemplateImage = cv2.resize( potTemplateImage.astype(np.uint8), (potImage.shape[1], potImage.shape[0])) self.potPyramid = cd.createImagePyramid(potTemplateImage) XSteps = int(round(self.traySize[0] / float(self.potSize[0]))) YSteps = int(round(self.traySize[1] / float(self.potSize[1]))) StepX = self.traySize[0] // XSteps StepY = self.traySize[1] // YSteps self.potLocs2 = [] self.potLocs2_ = [] potGridSize = [4, 5] for trayLoc in self.trayLocs: if trayLoc is None: self.potLocs2.append(None) continue StartX = trayLoc[0] - self.traySize[0] // 2 + StepX // 2 StartY = trayLoc[1] + self.traySize[1] // 2 - StepY // 2 SearchRange = [self.potPyramid[0].shape[1] // 4, self.potPyramid[0].shape[0] // 4] # SearchRange = [32, 32] locX = np.zeros(potGridSize) locY = np.zeros(potGridSize) for k in range(potGridSize[0]): for l in range(potGridSize[1]): estimateLoc = [StartX + StepX * k, StartY - StepY * l] score, loc, angle = cd.matchTemplatePyramid( self.imagePyramid, self.potPyramid, RotationAngle=0, EstimatedLocation=estimateLoc, NoLevels=3, SearchRange=SearchRange) locX[k, l], locY[k, l] = loc # correct for detection error potLocs = [] potLocs_ = [] diffXX = locX[1:, :] - locX[:-1, :] diffXY = locX[:, 1:] - locX[:, :-1] diffYX = locY[1:, :] - locY[:-1, :] diffYY = locY[:, 1:] - locY[:, :-1] diffXXMedian = np.median(diffXX) diffXYMedian = np.median(diffXY) diffYXMedian = np.median(diffYX) diffYYMedian = np.median(diffYY) for k in range(potGridSize[0]): for l in range(potGridSize[1]): locX[k, l] = trayLoc[0] + diffXXMedian * (k - (potGridSize[0] - 1.0) / 2.0) + \ diffXYMedian * (l - (potGridSize[1] - 1.0) / 2.0) locY[k, l] = trayLoc[1] + diffYXMedian * (k - (potGridSize[0] - 1.0) / 2.0) + \ diffYYMedian * (l - (potGridSize[1] - 1.0) / 2.0) # this fixes perpective shift # TODO: need a more elegant solution locY[k, l] = locY[k, l] + 10 potLocs.append([locX[k, l], locY[k, l]]) potLocs_.append(estimateLoc) self.potLocs2.append(potLocs) self.potLocs2_.append(potLocs_) # Create a new ImagePotMatrix with newly discovered locations ipmPrev = None if context.hasSubSecName("ipmPrev"): ipmPrev = context.ipmPrev # Calculate growM with potSize from potdetect component. growM = 0 if isinstance(self.potSize, list) and len(self.potSize) == 2: growM = round(max(self.potSize) / 2) else: # if no user vals, we try to calculate it. flattened = list(chain.from_iterable(self.potLocs2)) sortDist = np.sort(spatial.distance.pdist(flattened)) sortDist = sortDist[0:len(flattened)] growM = round(np.median(sortDist) / 2) tsi.ipm = tm_pot.ImagePotMatrix( tsi, pots=[], growM=growM, ipmPrev=ipmPrev) potID = self.startingPotId for tray in self.potLocs2: trayID = 1 for c in tray: # c => center m = dict([[x, context.metas.getVal(x)[potID]] for x in context.metas.listSubSecNames() if potID in context.metas.getVal(x).keys()]) try: r = tm_pot.ImagePotRectangle(c, tsi.pixels.shape, growM=growM) except: raise PCExPotRectangleDimsOutOfImage(potID, c, tsi.pixels.shape) p = tm_pot.ImagePotHandler(potID, r, tsi.ipm, metaids=m) p.setMetaId("trayID", trayID) tsi.ipm.addPot(p) potID += 1 trayID += 1 return([tsi])