Friday, July 6, 2012

Convexity defects in a cluster of mouse chromosomes

Just a little trial to explore cv2.convexityDefects() on a cluster of mouse chromosomes:

The cluster consists in five touching mouse chromosomes. The aim is to use cv2 to display the contour of the particle, its convex hull, and to see what it is possible to do with convexityDefects function implemented in OpenCv 2.4.2 which provides now the big advantage of handling numpy array. The python script used is largely inspired from abid rahman's blog:

# -*- coding: utf-8 -*-
"""
Created on Wed Jul  4 14:43:42 2012

@author: jean-pat
"""

import cv2
import numpy as np
import os
import pylab as plb
print cv2.__version__

user=os.path.expanduser("~")
workdir=os.path.join(user,"QFISH","JPPAnimal","JPP52","11","DAPI","particles")

file="part25.png"
complete_path=os.path.join(workdir,file)

img = cv2.imread(complete_path)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,gray = cv2.threshold(gray,1,255,0)
print ret
gray2 = gray.copy()
mask = np.zeros(gray.shape,np.uint8)

contours, hier = cv2.findContours(gray,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
print hier
cv2.drawContours(img,contours,0,(0,255,0),1)
cnt = contours[0]
hull = cv2.convexHull(cnt,returnPoints = False)
#print hull
approx = cv2.approxPolyDP(cnt,0.05*cv2.arcLength(cnt,True),True)
print 'approx',approx

print 'contours',type(cnt), cnt.dtype, len(contours)
defects = cv2.convexityDefects(cnt,hull)
print defects
for i in range(defects.shape[0]):
    s,e,f,d = defects[i,0]
    start = tuple(cnt[s][0])
    end = tuple(cnt[e][0])
    far = tuple(cnt[f][0])
    cv2.line(img,start,end,[255,0,0],1)
    cv2.circle(img,far,5,[0,0,255],1)

plb.imshow(img)
plb.show()

    
The result is :

Strangely, some convexity defects (blue circles) of the particle contour (green curve) are very close to the particle convex hull (red curve). Four defects are detected on the contour where the chromosomes touch each other as waited. Those contact regions correspond to "neck" on the contour curve, and only one side of the neck is detected.
At first sight, there is nine false positive points, four well detected points and four non detected points (the other side of the "necks").

From the script, the content of the defect variable is:

[[[  214   216   215   689]]
[[  216   218   217   114]]
[[    0    30    19  2444]]
 [[   30    32    31   234]]
 [[   32    34    33   201]]
 [[   34    38    37   278]]
 [[   38    71    56  5658]]
 [[   72    78    73   114]]
 [[   78    94    87  3133]]
 [[   96    98    97   114]]
 [[   98   106   101   297]]
 [[  106   120   111   364]]
 [[  121   212   179 12452]]]

The convexity defect is a list of vectors of the form:

(start_index, end_index, farthest_pt_index, fixpt_depth)

so it should be possible to filter the points too close to the convex hull.

1 comment:

Anonymous said...

when I use convexityDefects, it get the error: AttributeError: 'module' object has no attribute 'convexityDefects'

do you know something about this??
I'm using opencv 2.4.6 on python 2.7 in ubuntu 12.04