kymograph

Antoine Basset

Research

As a PhD student at Inria (team Serpico), I work on the detection and estimation of dynamic events in image sequences. I focus on fluorescence microscopy image sequences and videos of crowded scenes.

Membrane dynamics

membrane event
Hover over the image to play the framed membrane event

Assessing the dynamics of plasma membrane events in live cell fluorescence microscopy is of paramount interest to understand cell mechanisms. In collaboration with UMR144, we develop methods to detect vesicle fusion events, and then estimate the associated dynamics in image sequences of total internal reflection fluorescence microscopy (TIRFM). Various dynamic models (including translation, diffusion and dissociation) are tested to classify the dynamics of each detected event.

Spot detection

spot detection
Hover over the image to see our vesicle segmentation results

To quantitatively analyze dynamic phenomena such as the aforementioned membrane dynamics, subcellular particles of interest have to be accurately detected. In 2014, we proposed ATLAS, a method enabling the segmentation of vesicles in fluorescence microscopy images. The segmentation stage amounts to thresholding the Laplacian of Gaussian (LoG) of the image. The optimal LoG scale is automatically selected in a scale-space framework, and the threshold is locally deduced from a user-specified probability of false alarm.

Crowd motion analysis

motion patterns
Hover over the image to see our motion pattern segmentation results

Assessing crowd behaviors from videos is a difficult task while of interest in many applications. We have defined a novel approach, which identifies, from two successive frames only, crowd behaviors expressed by simple image motion patterns. It relies on the estimation of a collection of sub-affine motion models in the image, a local motion classification based on a penalized likelihood criterion, and a regularization stage involving inhibition and reinforcement factors. Relying on this motion descriptor, we have also developed an original and simple method for recovering the dominant paths followed by people in the observed scene. We are now working on the on-line detection and localization of abnormal behaviors in videos of crowded scenes.

Publications

SetBibliographyStyle($this->GetDefaultStyle()); $this->SetBibliographyOrder($this->GetDefaultOrder()); if($num_args > 0) $this->ParseFiles($args); } ////////////////////////////////////////////////////////////////////////////// // Get/Set ////////////////////////////////////////////////////////////////////////////// // bib-style = numeric cite(..) [1,2] // citet(..) Vreeken & van Leeuwen [1]; Vreeken et al. [2] // = abbrv [VvL12,VvlS07] // Vreeken & van Leeuwen [VvL12]; Vreeken et al. [VvlS07] // = natbib (Vreeken & van Leeuwen, 2012); (Vreeken et al., 2007) // Vreeken & van Leeuwen (2012); Vreeken et al. (2007) function SetBibliographyStyle($style) { if($style == 'abbrv') { $this->refPrinter = new AbbrvPrinter(); } else if($style == 'natbib') { $this->refPrinter = new NatbibPrinter(); } else if($style == 'numeric') { $this->refPrinter = new NumericPrinter(); } else if($style == 'journal') { $this->refPrinter = new JournalPrinter(); } else if($style == 'conf') { $this->refPrinter = new ConfPrinter(); } else if($style == 'nconf') { $this->refPrinter = new NConfPrinter(); } else if($style == 'report') { $this->refPrinter = new ReportPrinter(); } else die('unknown style'); } function GetDefaultStyle() { return 'numeric'; } // bib-order = alphabetic // = usage function SetBibliographyOrder($order) { if($order == 'alphabetic') { $order = array('author' => 'asc', 'year' => 'asc', 'title' => 'asc', 'usage' => 'asc'); } else if(is_string($order)) { $pu = strpos($order, '_'); $fd = ($pu != false ? substr($order, 0, $pu) : $order); $sd = ($pu != false ? substr($order, $pu+1) : 'asc'); // default to ascending $order = array($fd => $sd); } // normalize 'asc' to 'a', and 'desc' to 'd' foreach($order as $f => $d) if($d == 'asc') $order[$f] = 'a'; else if($d == 'desc') $order[$f] = 'd'; $this->order = $order; } // 'asc' or 'a' for ascending (default), 'desc' or 'd' for descending function GetDefaultOrder() { return array('usage' => 'asc', 'author' => 'asc', 'year' => 'asc', 'title' => 'asc'); } ////////////////////////////////////////////////////////////////////////////// // Load Citation Database ////////////////////////////////////////////////////////////////////////////// function ParseFiles($files) { foreach($files as $file) { if(is_string($file)) { $fname = ( stripos($file, ".bib")!=false ? $file : $file . '.bib' ); if(file_exists($fname)) { $this->Parse( $fname ); } } } } function Parse($pathname) { $file = file($pathname); $rawblock = ''; $inblock = false; foreach($file as $line) { $line = str_replace('\\textsc','', $line); $line = str_replace('\\textit','', $line); $pattern = "/\\$(.*)\\$/i"; $replacement = '${1}'; $line = preg_replace($pattern, $replacement, $line); $pattern = "/\{\\\'(\w+)\}/"; $replacement = '&${1}acute;'; $line = preg_replace($pattern, $replacement, $line); $pattern = "/\\\'\{(\w+)\}/"; $line = preg_replace($pattern, $replacement, $line); $pattern = '/\{\\\"(\w+)\}/'; $replacement = '&${1}uml;'; $line = preg_replace($pattern, $replacement, $line); $pattern = '/\\\"\{[\\\]?(\w+)\}/'; $line = preg_replace($pattern, $replacement, $line); $replacement = 'ç'; $line = str_replace('\cc', $replacement, $line); $line = preg_replace($pattern, $replacement, $line); $pattern = '/\\\c\{c\}/'; $line = preg_replace($pattern, $replacement, $line); $pattern = '/\{\\\noopsort\{\w+\}\}/'; $line = preg_replace($pattern, '', $line); $pattern = '/=\s*"/'; $line = preg_replace($pattern, '= {', $line); $line = str_replace('"','}', $line); $line = str_replace('\\delta','δ', $line); $line = str_replace('$','', $line); $seg = $line; // check if starts with @ ... $segT = trim($seg); if(strlen($segT) > 0 && $segT[0] == '}') { $rawblock .= ' '.trim(substr($seg,0,strpos($seg,'%%') == false ? strlen($seg) : strpos($seg,'%%')), " \n\r"); $this->ParseEntry($rawblock); $rawblock = ''; $inblock = false; } else if(strlen($segT) > 0 && $segT[0] == '@') { // starts something new $this->ParseEntry($rawblock); $rawblock = ''; $inblock = true; } $pc = strpos($seg,'%%') == false ? strlen($seg) : strpos($seg,'%%'); if($inblock === true) $rawblock .= ' '.trim(substr($seg,0,$pc), " \n\r"); } if($rawblock != '') $this->ParseEntry($rawblock); } function ParseEntry($rb) { $rb = trim($rb); if($rb == '') return; $entry = array(); $pa = strpos($rb, '{'); $pc = strpos($rb, ','); if($pa == false) { return; } $entry['type'] = strtolower(substr($rb, 1, $pa-1)); if($entry['type'] == 'preamble') return; $entry['key'] = Bibtex::NormalizeKey(substr($rb, $pa+1, $pc-$pa-1)); $rb = substr($rb, $pc+1, -1); $rawfields = array(); $start = 0; $nest = 0; for($i=0; $i < strlen($rb); $i++) { if($rb[$i] == ',' && $nest == 0) { $start = $i+1; } else if($rb[$i] == '{' || ($rb[$i] == '"' && ($i+1 < strlen($rb) && ($rb[$i+1] != ',' && $rb[$i+1] != "\n")))) { $nest++; } else if($rb[$i] == '}' || ($rb[$i] == '"' && ( ($i+1 < strlen($rb) && ($rb[$i+1] == ',' || $rb[$i+1] == "\n" || $rb[$i+1] == "\r"))) || ($i+1==strlen($rb))) ) { $nest--; if($nest == 0) { $rawfields[] = trim(substr($rb, $start, $i-$start+1)); $start = $i+1; } } } foreach($rawfields as $field) { $fieldname = strtolower(trim(substr($field, 0, strpos($field, '=')))); $fieldval = substr(trim(substr($field, strpos($field, '=')+1)),1,-1); $entry[$fieldname] = $fieldval; } // pre-handle author array if(isset($entry['author'])) { $entry['author'] = Bibtex::NormalizeAuthorStr($entry['author']); } // pre-handle editor array if(isset($entry['editor'])) { $entry['editor'] = Bibtex::NormalizeAuthorStr($entry['editor']); } // pre-handle pagefrom/to if(isset($entry['pages'])) { $pattern = '/^([0-9]+)[^0-9]+([0-9]+)$/'; if(preg_match($pattern, $entry['pages'], $match)) $entry['pages'] = $match[1] . '-' . $match[2]; } // pre-handle booktitle if(isset($entry['booktitle'])) { $entry['booktitle'] = str_replace('{','', str_replace('}','',str_replace('`', '\'', $entry['booktitle']))); } // filter out {'s foreach($entry as $field => $val) { $val = str_replace('{', '', $val); $val = str_replace('}', '', $val); $entry[$field] = $val; } $this->bibarr[$entry['key']] = $entry; } ////////////////////////////////////////////////////////////////////////////// // Helper-methods ////////////////////////////////////////////////////////////////////////////// function NormalizeKey($key) { return str_replace('/', '_', str_replace(':', '_', trim($key))); } function NormalizeAuthorStr($authorstr) { $aarr = explode(' and ', $authorstr); $aarr = array_map('trim', $aarr); for($i=0; $i < count($aarr); $i++) { if(strpos($aarr[$i], ',') == false) { // no first/lastname indicator, let's do that ourselves $pa = strpos($aarr[$i], '{') != false && (strpos($aarr[$i],'{') == 0 || $aarr[$i][strpos($aarr[$i],'{')-1] == ' ' || $aarr[$i][strpos($aarr[$i],'{')-1] == '.') ? strpos($aarr[$i], '{') : false; $pl = ($pa == true) ? strpos($aarr[$i], '{') : strrpos($aarr[$i], ' '); $lastname = trim(substr($aarr[$i], $pl+1, ($pa && strpos($aarr[$i], '}', $pl) != false ? strpos($aarr[$i], '}', $pl) - $pl : strlen($aarr[$i])-$pl)-1) ); $firstname = trim(substr($aarr[$i], 0, $pl)); $fn = explode(' ', str_replace('.', '', str_replace('-', ' ', $firstname))); $fn2 = ''; for($j=0; $j < count($fn); $j++) { if(strlen($fn[$j]) > 0) $fn2 .= $fn[$j][0] . '.'; } $aarr[$i] = $lastname . ', ' . $fn2; } else { $na = explode(',', $aarr[$i]); $fn = explode(' ', str_replace('.', '', str_replace('-', ' ', trim($na[1])))); $fn2 = ''; for($j=0; $j < count($fn); $j++) { if(strlen($fn[$j]) > 0) $fn2 .= $fn[$j][0] . '.'; } $aarr[$i] = $na[0] . ', ' . $fn2; } } return implode(' and ', $aarr); } ////////////////////////////////////////////////////////////////////////////// // Save Citation Database ////////////////////////////////////////////////////////////////////////////// // ...later... ////////////////////////////////////////////////////////////////////////////// // Interact with Citation Database ////////////////////////////////////////////////////////////////////////////// /// Impl for BibArray function HasEntry($key) { $key = Bibtex::NormalizeKey($key); return isset($this->bibarr[$key]); } function GetEntry($key) { $key = Bibtex::NormalizeKey($key); return isset($this->bibarr[$key]) ? $this->bibarr[$key] : false; } ////////////////////////////////////////////////////////////////////////////// // Cite-variants, for in-line selection of entries ////////////////////////////////////////////////////////////////////////////// function Citep() { $args = func_get_args(); CiteRefs('p', $args); } function Citet() { $args = func_get_args(); CiteRefs('t', $args); } function CiteRefs($style, $args) { $style = $style == 't' ? 't' : 'p'; $num_args = count($args); for($i=0; $i < $num_args; $i++) { if(is_object($args[$i])) continue; if(!isset($this->used[$args[$i]])) { $entry = $this->GetEntry($args[$i]); if($entry === false) $this->used[$args[$i]] = array('key' => $args[$i], 'ref' => false, 'cited' => true, 'selected' => false, 'entry' => $entry); else $this->used[$args[$i]] = array('key' => $args[$i], 'ref' => $this->usedCnt++, 'cited' => true, 'selected' => false, 'entry' => $entry); } } if($this->scanning === false) { echo $this->refPrinter->StartCiteStr(); echo ($style == 'p') ? $this->refPrinter->StartListStr() : ''; for($i=0; $i < $num_args-1; $i++) { $entry = $this->GetEntry($args[$i]); $usage = $this->used[$args[$i]]; echo ($style == 'p') ? $this->refPrinter->ListRefStr($entry, $usage) : $this->refPrinter->TextualRefStr($entry, $usage); echo $this->refPrinter->SepListStr(); } $entry = $this->GetEntry($args[$num_args-1]); $usage = $this->used[$args[$num_args-1]]; echo ($style == 'p') ? $this->refPrinter->ListRefStr($entry, $usage) : $this->refPrinter->TextualRefStr($entry, $usage); echo ($style == 'p') ? $this->refPrinter->EndListStr() : ''; echo $this->refPrinter->EndCiteStr(); } } ////////////////////////////////////////////////////////////////////////////// // Pre-scanning of Cites, required for non-usage Bibliography orders ////////////////////////////////////////////////////////////////////////////// function IncludeBibContent($pathname, $bib = false) { if($bib != false) eval ('global '.$bib.';'); Bibtex::ScanContentForCites($pathname, $bib); include $pathname; } function ScanContentForCites($pathname, $bib) { if($bib != false) eval ('global '.$bib.';'); $this->ResetBibliography(); $this->scanning = true; ob_start(); include $pathname; ob_end_clean(); $this->OrderBibliography(); $this->scanning = false; $this->scanned = true; } function ResetBibliography() { $this->scanning = false; $this->scanned = false; $this->used = array(); $this->usedCnt = 0; } ////////////////////////////////////////////////////////////////////////////// // Order Bibliography ////////////////////////////////////////////////////////////////////////////// // impl for Bibarray function OrderBibliography() { if(is_string($this->order)) // this shouldn't happen, don't set order yourself. SetBibliographyOrder($this->order); if(!is_array($this->order)) { // this definitely shouldn't happen echo "Error ordering bibliography: incorrect order specified"; return; } $order = $this->order; // only order on usage, already added in right order, so nothing to order! if(count($order) == 1 && isset($order['usage']) && $this->scanned == false) { return; } $arr = array(); $numCited = 0; $numSelected = 0; foreach($this->used as $key => $val) { if($val['ref'] === false) continue; else { $arr[] = $key; $numSelected += $val['selected'] == true ? 1 : 0; $numCited += $val['selected'] == true ? 1 : 0; } } // for each entry $i to be in reference list for($i=0; $i< count($arr)-1; $i++) { // for each other entry $j for($j=$i+1; $j< count($arr); $j++) { $k = 0; // check whether $i < $j foreach($order as $f => $d) { if($f == 'usage' || $f == 'cited') { $g = ($f == 'usage' ? 'ref' : 'cited'); $k = Bibtex::CmpString($this->used[$arr[$i]][$g], $this->used[$arr[$j]][$g], $d); } else { $a = $this->used[$arr[$i]]['entry']; $b = $this->used[$arr[$j]]['entry']; if(($a === false && $b !== false) || ($a !== false && $b !== false && (!isset($a[$f]) || $a[$f] === NULL) && (isset($b[$f]) && $b[$f] !== NULL))) $k = -1; else if(($a !== false && $b === false) || ($a !== false && $b !== false && (isset($a[$f]) && $a[$f] !== NULL) && (!isset($b[$f]) || $b[$f] === NULL))) $k = 1; else if((isset($a[$f]) && $a[$f] !== NULL) && (isset($b[$f]) && $b[$f] !== NULL)) $k = Bibtex::CmpString($a[$f], $b[$f], $d); } if($k != 0) break; } if($k == 1) { $tmp = $arr[$j]; $arr[$j] = $arr[$i]; $arr[$i] = $tmp; } } } $c = 0; $newUsed = array(); foreach($arr as $a) { $newUsed[$a] = $this->used[$a]; $newUsed[$a]['ref'] = $c++; } foreach($this->used as $k => $v) { if($this->used[$k]['ref'] === false) $newUsed[$k] = $this->used[$k]; } $this->used = $newUsed; } ////////////////////////////////////////////////////////////////////////////// // Ordering Helper-methods ////////////////////////////////////////////////////////////////////////////// function CmpEntriesYear($a, $b, $d) { if($a['year'] < $b['year']) return ($d == 'a' ? -1 : 1); else if($a['year'] > $b['year']) return ($d == 'a' ? 1 : -1); else return 0; } function CmpString($a, $b, $d) { return strcmp(($d == 'a' ? strtolower($a) : strtolower($b)), ($d == 'a' ? strtolower($b) : strtolower($a))); } function CmpEntriesAuthors($a, $b, $d) { return Bibtex::CmpString($a['author'], $b['author'], $d); } function CmpEntriesTitles($a, $b, $d) { return Bibtex::CmpString($a['title'], $b['title'], $d); } function CmpEntriesCited($a, $b, $d) { if($a['sel'] == true && $b['sel'] == true) return 0; else if($s['sel'] == true) return ($d == 'a' ? 1 : 0); else return ($d == 'a' ? -1 : 0); } ////////////////////////////////////////////////////////////////////////////// // Query-based Selection ////////////////////////////////////////////////////////////////////////////// // takes an array, where key => valye identifies the key for which the value should match what value (done through preg_match) // impl for BibArray function Select($queryArray) { if($this->scanning == true) return; foreach($this->bibarr as $entry) { $sel = true; foreach($queryArray as $field => $val) { if($field[0]>='0' && $field[0]<='9') // jv says: don't really see the point of this? $field=substr($field,1); if(is_array($val)) { $psel = false; foreach($val as $v) { if(isset($entry[$field])) { if($field == 'key') $v = Bibtex::NormalizeKey($v); if(stripos($entry[$field], $v) !== false) { $psel = true; break; } } } $sel = $psel; } else if( !isset($entry[$field]) || ($field == 'key' && $entry['key'] != Bibtex::NormalizeKey($val)) || (stripos($entry[$field], (string) $val) === false)) { $sel = false; } } if($sel == true) { $this->SelectEntry($entry['key'], $entry); } } } function SelectEntry($key, $entry = false) { if(!isset($this->used[$key])) { $this->used[$key]['ref'] = $this->usedCnt++; $this->used[$key]['selected'] = true; $this->used[$key]['cited'] = false; $this->used[$key]['entry'] = $entry; } else { $this->used[$key]['selected'] = true; $this->used[$key]['entry'] = $this->used[$key]['entry'] === false ? $entry : $this->used[$key]['entry']; } } ////////////////////////////////////////////////////////////////////////////// // Print Bibliography ////////////////////////////////////////////////////////////////////////////// // Prints elements in $this->used, in the order of $this->used. // If other order is desired, use SetBibliographyOrder(..) in advance. function PrintBibliography() { if($this->scanning === true) return; echo '' . "\n"; $this->OrderBibliography(); foreach($this->used as $key => $info) { if($info['ref'] === false) continue; $entry = isset($info['entry']) ? $info['entry'] : $this->GetEntry($key); echo $this->refPrinter->BibliographyEntryStr($entry, $this->used[$key]); } echo '
' . "\n"; } function PrintReversedBibliography() { if($this->scanning === true) return; echo '' . "\n"; $this->OrderBibliography(); foreach(array_reverse($this->used) as $key => $info) { if($info['ref'] === false) continue; $entry = isset($info['entry']) ? $info['entry'] : $this->GetEntry($key); echo $this->refPrinter->BibliographyEntryStr($entry, $this->used[$key]); } echo '
' . "\n"; } function PrintBibliographyCitedOnly() { if($this->scanning === true) return; echo '' . "\n"; $this->OrderBibliography(); foreach($this->used as $key => $info) { if($info['ref'] === false || (isset($info['selected']) && $info['selected'] === true) || (isset($info['cited']) && $info['cited'] === false)) { continue; } $entry = isset($info['entry']) ? $info['entry'] : $this->GetEntry($key); echo $this->refPrinter->BibliographyEntryStr($entry, $this->used[$key]); } echo '
' . "\n"; } function PrintBibliographySelectedOnly() { if($this->scanning === true) return; echo '' . "\n"; $this->OrderBibliography(); foreach($this->used as $key => $info) { if($info['ref'] === false || (isset($info['selected']) && $info['selected'] === false) || (isset($info['cited']) && $info['cited'] === true)) continue; $entry = isset($info['entry']) ? $info['entry'] : $this->GetEntry($key); echo $this->refPrinter->BibliographyEntryStr($entry, $this->used[$key]); } echo '
' . "\n"; } } function cite() { global $Site; $num_args = func_num_args(); $args = func_get_args(); $bibarg = ($num_args > 0 && is_object($args[0]) ? true : false); $bibobj = ($bibarg == true ? $args[0] : ((isset($Site) && isset($Site['bibtex']) && is_object($Site['bibtex'])) ? $Site['bibtex'] : false)); $bibargs = ($bibarg == true ? array_slice($args, 1) : $args); if($bibobj != false) $bibobj->CiteRefs('p', $bibargs); } function citep() { global $Site; $num_args = func_num_args(); $args = func_get_args(); $bibarg = ($num_args > 0 && is_object($args[0]) ? true : false); $bibobj = ($bibarg == true ? $args[0] : ((isset($Site) && isset($Site['bibtex']) && is_object($Site['bibtex'])) ? $Site['bibtex'] : false)); $bibargs = ($bibarg == true ? array_slice($args, 1) : $args); if($bibobj != false) $bibobj->CiteRefs('p', $bibargs); } function citet() { global $Site; $num_args = func_num_args(); $args = func_get_args(); $bibarg = ($num_args > 0 && is_object($args[0]) ? true : false); $bibobj = ($bibarg == true ? $args[0] : ((isset($Site) && isset($Site['bibtex']) && is_object($Site['bibtex'])) ? $Site['bibtex'] : false)); $bibargs = ($bibarg == true ? array_slice($args, 1) : $args); if($bibobj != false) $bibobj->CiteRefs('t', $bibargs); } ?>

Journal