def draw(self): if self.markers is not None: self.result[:] = self.markers cv2.watershed(self.img, self.result) img = MARKER_COLORS[self.result] self.draw_image(img, self.result_artist, draw=False) self.draw_image(self.img)
def segment_on_dt(a, img, gray): border = cv2.dilate(img, None, iterations=5) border = border - cv2.erode(border, None) dt = cv2.distanceTransform(img,cv2.DIST_L2,5) plt.subplot(3,3,4) plt.imshow(dt),plt.title('dt'),plt.xticks([]), plt.yticks([]) dt = ((dt - dt.min()) / (dt.max() - dt.min()) * 255).astype(np.uint8) _, dt2 = cv2.threshold(dt, 0, 255, cv2.THRESH_BINARY) dt2 = cv2.erode(dt2, None, iterations=2) # dt2 = cv2.adaptiveThreshold(dt, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 5, 2) # dt1 = peak_local_max(gray, indices=False, min_distance=10, labels=img, threshold_abs=5) # dt2 = peak_local_max(dt, indices=False, min_distance=5, labels=img, threshold_abs=0) lbl, ncc = label(dt2) plt.subplot(3,3,5) plt.imshow(dt2),plt.title('localMax'),plt.xticks([]), plt.yticks([]) # plt.subplot(3,3,6) # plt.imshow(ncc),plt.title('ncc'),plt.xticks([]), plt.yticks([]) lbl = lbl * (255/ncc) # Completing the markers now. lbl[border == 255] = 255 lbl = lbl.astype(np.int32) cv2.watershed(a, lbl) lbl[lbl == -1] = 0 lbl = lbl.astype(np.uint8) plt.subplot(3,3,6) plt.imshow(lbl),plt.title('lbl_out'),plt.xticks([]), plt.yticks([]) return 255 - lbl
def watershed(self,image, marker): """ Applies opencv's watershed method iteratively to an input image. An initial marker containing preliminary information on which pixels are foreground serves as additional input. The initial marker can be based on user input (color-picking), or can be constructed with an automatic marker strategy. The marker decides from which pixels the flooding in the watershed method may start. Finally, the marker is used to obtain a mask classifying every pixel into foreground or background. Args: image: An input image which is not altered marker: A marer suitable for use with opencv's grabcut iterations: The number of iterations grabcut may update the marker Returns: A mask image classifying every pixel into foreground or background """ if len(marker.shape) == 3: marker = marker[:,:,0] # convert the marker to the format watershed expects marker = np.int32(marker) # Use watershed to decide how to label the yet undecided regions. # This may produce may foreground areas labeld with different integers. cv2.watershed(image, marker) # Obtain the final mask by thresholding. Different foreground regions have different positive values. # We are only intrested in global foreground so we set all of them to be white, i.e. 255. mask_watershed = cv2.convertScaleAbs(marker) return mask_watershed
def watershed(image, grayed, edges, min_ratio, max_count): """ Applies watershed algorithm to 'image' with markers derived from 'edges' Args: image: original image grayed: grayed and optionally blurred version of 'image' edges: a binary image min_ratio: only contours in 'edges' with an area bigger are used as markers max_count: maximum number of segments to derive Returns segments, markers, count """ markers = edges.copy() _, markers1, _ = extract_segments( grayed, markers, min_ratio=min_ratio, max_count=max_count ) markers32 = numpy.int32(markers1) cv2.watershed(image, markers32) watersheded = cv2.convertScaleAbs(markers32) _, edges = cv2.threshold( watersheded, 1, 255, cv2.THRESH_BINARY_INV ) segments, markers, count = extract_segments( grayed, edges ) return segments, markers, count
def subtract_back(self,frm): #dst=self.__back__-self.__foreground__ temp=np.zeros((config.height,config.width),np.uint8) self.__foreground__=cv2.blur(self.__foreground__,(3,3)) dst=cv2.absdiff(self.__back__,self.__foreground__) #dst=cv2.adaptiveThreshold(dst,255,cv.CV_THRESH_BINARY,cv.CV_ADAPTIVE_THRESH_GAUSSIAN_C,5,10) val,dst=cv2.threshold(dst,0,255,cv.CV_THRESH_BINARY+cv.CV_THRESH_OTSU) fg=cv2.erode(dst,None,iterations=1) bg=cv2.dilate(dst,None,iterations=4) _,bg=cv2.threshold(bg,1,128,1) mark=cv2.add(fg,bg) mark32=np.int32(mark) #dst.copy(temp) #seq=cv.FindContours(cv.fromarray(dst),self.mem,cv.CV_RETR_EXTERNAL,cv.CV_CHAIN_APPROX_SIMPLE) #cntr,h=cv2.findContours(dst,cv.CV_RETR_EXTERNAL,cv.CV_CHAIN_APPROX_SIMPLE) #print cntr,h #cv.DrawContours(cv.fromarray(temp),seq,(255,255,255),(255,255,255),1,cv.CV_FILLED) cv2.watershed(frm, mark32) self.final_mask=cv2.convertScaleAbs(mark32)
def segment_on_dt(a, img): ''' find foreground ''' fg=cv2.dilate(img,None, iterations=5) fg=fg-cv2.erode(fg, None) dt=cv2.distanceTransform(img, 2, 3) dt=((dt-dt.min())/(dt.max()-dt.min())*255).astype(np.uint8) _, dt=cv2.threshold(dt, 0, 255, cv2.THRESH_BINARY) lbl, ncc=label(dt) lbl=lbl*(255/ncc) ''' Completing the markers now ''' lbl[fg==255]=255 lbl=lbl.astype(np.int32) cv2.watershed(a, lbl) lbl[lbl==-1]=0 lbl=lbl.astype(np.uint8) return 255-lbl
def segment_watershed(img): gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh=cv2.threshold(gray, 0,255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) ''' foreground region ''' fg=cv2.erode(thresh,None, iterations=2) ''' background region ''' bg=cv2.dilate(thresh, None,iterations=3) ret, bg=cv2.threshold(bg,1,128,1) ''' add both fg and bg ''' marker=cv2.add(fg, bg) ''' convert into 32SC1 ''' marker32=np.int32(marker) ''' apply watershed ''' cv2.watershed(img, marker32) m=cv2.convertScaleAbs(marker32) ''' threshold it properly to get the mask and perform bitwise_and with the input image ''' ret, thresh=cv2.threshold(m,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) result=cv2.bitwise_and(img, img,mask=thresh) return result
def watershed(self): m = self.markers.copy() cv2.watershed(self.img, m) overlay = self.colors[np.maximum(m, 0)] cv2.imshow('over', overlay) vis = cv2.addWeighted(self.img, 0.5, overlay, 0.5, 0.0, dtype=cv2.CV_8UC3) cv2.imshow('watershed', vis)
def detect_shirt2(self): self.hsv=cv2.cvtColor(self.norm_rgb,cv.CV_BGR2HSV) self.hue,s,_=cv2.split(self.hsv) _,self.dst=cv2.threshold(self.hue,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) self.fg=cv2.erode(self.dst,None,iterations=3) self.bg=cv2.dilate(self.dst,None,iterations=1) _,self.bg=cv2.threshold(self.bg,1,128,1) mark=cv2.add(self.fg,self.bg) mark32=np.int32(mark) cv2.watershed(self.norm_rgb,mark32) m=cv2.convertScaleAbs(mark32) _,m=cv2.threshold(m,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) cntr,h=cv2.findContours(m,cv.CV_RETR_EXTERNAL,cv.CV_CHAIN_APPROX_SIMPLE) print len(cntr) #print cntr[0].shape #cntr[1].dtype=np.float32 #ret=cv2.contourArea(np.array(cntr[1])) #print ret #cntr[0].dtype=np.uint8 cv2.drawContours(m,cntr,-1,(255,255,255),3) cv2.imshow("mask_fg",self.fg) cv2.imshow("mask_bg",self.bg) cv2.imshow("mark",m)
def watershed(self): m = self.markers.copy() cv2.watershed(self.img,m) self.img[m == -1] = [255,0,0] overlay = self.colors[np.maximum(m, 0)] vis = cv2.addWeighted(self.img, 0.5, overlay, 0.5, 0.0, dtype=cv2.CV_8UC3) self.DisplayandSave('watershed', vis)
def process(self, args): """ Use the Watershed algorithm from the opencv package to the selected color channels of the current image. Args: | *args* : a list containing image array and Graph object """ # convert image to grayscale and threshold it with the best threshold # value usinf otsu binarization image = args[0] im_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(im_gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # erode will be used to create the foreground region (marked with 255) fg = cv2.erode(thresh, None, iterations=self.fgiter) # dilate will be used to reduce the background region. Black region # will be set to 128 and is marked as background bgt = cv2.dilate(thresh, None, iterations=self.bgiter) ret, bg = cv2.threshold(bgt, 1, 128, 1) # create marker with foreground and background region marker = cv2.add(fg, bg) marker32 = np.int32(marker) # use watershed and convert result back cv2.watershed(image, marker32) m = cv2.convertScaleAbs(marker32) # threshold to get the mask ret, thresh = cv2.threshold(m, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) self.result['img'] = cv2.bitwise_and(image, image, mask=thresh)
def get_fish_contour(data, cal): color_image = cv2.cvtColor(data.array, cv2.COLOR_GRAY2BGR) delta_image(data, cal) threshold_by_type(data) erode(data) distance_transform(data) threshold_by_type(data, otsu=False, thresh=5) markers = data.array.copy() dilate(data, iterations=7) border = data.array.copy() border = border - cv2.erode(border, None) markers, num_blobs = ndimage.measurements.label(markers) markers[border == 255] = 255 markers = markers.astype(np.int32) cv2.watershed(image=color_image, markers=markers) markers[markers == -1] = 0 markers = 255 - markers.astype(np.uint8) image = FFImage(markers, meta=data.meta, log=data.log) annotate_hu_moments(image) image.meta['timestamp'] = time.time() return image.meta
def segment_on_dt(img): #http://stackoverflow.com/questions/11294859/how-to-define-the-markers-for-watershed-in-opencv img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) _, img_bin = cv2.threshold(img_gray, 0, 255,cv2.THRESH_OTSU) img_bin = cv2.morphologyEx(img_bin, cv2.MORPH_OPEN,numpy.ones((3, 3), dtype=int)) border = cv2.dilate(img_bin, None, iterations=5) border = border - cv2.erode(border, None) dt = cv2.distanceTransform(img_bin, 2, 3) dt = ((dt - dt.min()) / (dt.max() - dt.min()) * 255).astype(numpy.uint8) _, dt = cv2.threshold(dt, 180, 255, cv2.THRESH_BINARY) lbl, ncc = label(dt) lbl = lbl * (255/ncc) # Completing the markers now. lbl[border == 255] = 255 lbl = lbl.astype(numpy.int32) cv2.watershed(img, lbl) lbl[lbl == -1] = 0 lbl = lbl.astype(numpy.uint8) result = 255 - lbl result[result != 255] = 0 result = cv2.dilate(result, None) img[result == 255] = (0, 0, 255) return img
def remove_pectoral(self, img, breast_mask, high_int_threshold=.8, morph_kn_size=3, n_morph_op=7, sm_kn_size=25): '''Remove the pectoral muscle region from an input image Args: img (2D array): input image as a numpy 2D array. breast_mask (2D array): high_int_threshold ([int]): a global threshold for high intensity regions such as the pectoral muscle. Default is 200. morph_kn_size ([int]): kernel size for morphological operations such as erosions and dilations. Default is 3. n_morph_op ([int]): number of morphological operations. Default is 7. sm_kn_size ([int]): kernel size for final smoothing (i.e. opening). Default is 25. Returns: an output image with pectoral muscle region removed as a numpy 2D array. Notes: this has not been tested on .dcm files yet. It may not work!!! ''' # Enhance contrast and then thresholding. img_equ = cv2.equalizeHist(img) if high_int_threshold < 1.: high_th = int(img.max()*high_int_threshold) else: high_th = int(high_int_threshold) maxval = self.max_pix_val(img.dtype) _, img_bin = cv2.threshold(img_equ, high_th, maxval=maxval, type=cv2.THRESH_BINARY) pect_marker_img = np.zeros(img_bin.shape, dtype=np.int32) # Sure foreground (shall be pectoral). pect_mask_init = self.select_largest_obj(img_bin, lab_val=maxval, fill_holes=True, smooth_boundary=False) kernel_ = np.ones((morph_kn_size, morph_kn_size), dtype=np.uint8) pect_mask_eroded = cv2.erode(pect_mask_init, kernel_, iterations=n_morph_op) pect_marker_img[pect_mask_eroded > 0] = 255 # Sure background - breast. pect_mask_dilated = cv2.dilate(pect_mask_init, kernel_, iterations=n_morph_op) pect_marker_img[pect_mask_dilated == 0] = 128 # Sure background - pure background. pect_marker_img[breast_mask == 0] = 64 # Watershed segmentation. img_equ_3c = cv2.cvtColor(img_equ, cv2.COLOR_GRAY2BGR) cv2.watershed(img_equ_3c, pect_marker_img) img_equ_3c[pect_marker_img == -1] = (0, 0, 255) # Extract only the breast and smooth. breast_only_mask = pect_marker_img.copy() breast_only_mask[breast_only_mask == -1] = 0 breast_only_mask = breast_only_mask.astype(np.uint8) breast_only_mask[breast_only_mask != 128] = 0 breast_only_mask[breast_only_mask == 128] = 255 kernel_ = np.ones((sm_kn_size, sm_kn_size), dtype=np.uint8) breast_only_mask = cv2.morphologyEx(breast_only_mask, cv2.MORPH_OPEN, kernel_) img_breast_only = cv2.bitwise_and(img_equ, breast_only_mask) return (img_breast_only, img_equ_3c)
def split(self): """Split the region according to the normalized cut criterion. Returns ------- list of CutRegion The regions created by splitting. float The normalized cut cost. """ if not cv2_available: raise ImportError('OpenCV >= 2.4.8 required') tmp_im = np.zeros(self.shape[0] * self.shape[1]) tmp_im[self.indices] = 1 labeled_array, num_features = ndimage.label(tmp_im.reshape(self.shape)) if num_features > 1: labeled_array = labeled_array.reshape(-1)[self.indices] segments = [] for i in range(1, num_features + 1): idx = np.nonzero(labeled_array == i)[0] segments.append(CutRegion(self.affinity_matrix[idx, :][:, idx], self.indices[idx], self.shape)) return segments, 0.0 C = normcut_vectors(self.affinity_matrix, 1) im = C[:, -2] im -= im.min() im /= im.max() markers = -np.ones(self.shape[0] * self.shape[1]).astype('uint16') markers[self.indices] = 0 markers[self.indices[im < 0.02]] = 1 markers[self.indices[im > 0.98]] = 2 markers = markers.reshape(self.shape) vis2 = 0.5 * np.ones(self.shape[0] * self.shape[1]) vis2[self.indices] = im vis2 *= (2 ** 8 - 1) vis2 = cv2.cvtColor(np.uint8(vis2.reshape(self.shape)), cv2.COLOR_GRAY2BGR) markers = np.int32(markers) cv2.watershed(vis2, markers) cut = ndimage.morphology.binary_dilation(markers == 2).reshape(-1)[ self.indices] cut[im > 0.98] = True cost = self._normalized_cut_cost(cut) for thresh in np.linspace(0, 1, 20)[1:-1]: tmp_cut = im > thresh tmp_cost = self._normalized_cut_cost(tmp_cut) if tmp_cost < cost: cost = tmp_cost cut = tmp_cut a = cut.nonzero()[0] a = cut.nonzero()[0] b = np.logical_not(cut).nonzero()[0] return ( [CutRegion(self.affinity_matrix[x, :][:, x], self.indices[x], self.shape) for x in [a, b] if len(x)], self._normalized_cut_cost(cut) )
def watershed(image, marker): m = marker.copy() cv2.watershed(image, m) m[m != 1] = 0 m *= 255 points = cv2.findNonZero(m.astype(np.uint8)) bound_rect = cv2.boundingRect(points) # x, y, w, h = bound_rect return bound_rect
def watershed(img, marker, device, debug): # Uses the watershed algorithm to detect boundry of objects # Needs a marker file which specifies area which is object (white), background (grey), unknown area (black) # img = image to perform watershed on needs to be 3D (i.e. np.shape = x,y,z not np.shape = x,y) # marker = a 32-bit image file that specifies what areas are what (2D, np.shape = x,y) cv2.watershed(img, marker) device += 1 if debug: print_image(marker, str(device) + 'watershed_img' + '.png') return device, marker
def segment_watershed(image, window=None): """Segments an image using watershed technique. Parameters ---------- image : (M, N, 3) array Image to process. window : tuple, (x, y, w, h) Optional subwindow in image. Returns ------- (rects, display) : list, (M, N, 3) array Region results and visualization image. """ import cv2 import numpy as np if window: subimage = np.array(image) x, y, w, h = window image = subimage[y:y + h, x:x + w] rects, display = segment_edges(image, variance_threshold=100, size_filter=0) h, w = image.shape[:2] initial = np.zeros((h, w), np.int32) for i, rect in enumerate(rects): cv2.drawContours(initial, [rect[4]], -1, 1, -1) display = np.zeros(initial.shape, dtype=np.uint8) segment_rects = [] for i, rect in enumerate(rects): regions = np.zeros(initial.shape, dtype=np.uint8) cv2.drawContours(regions, [rect[4]], -1, 2, -1) regions = cv2.erode(regions, None) regions = cv2.erode(regions, None) markers = initial.copy() markers[regions == 2] = 2 cv2.watershed(image, markers) display[markers == 2] = 255 contours, hierarchy = _find_contours(regions.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) segment_rects.extend([cv2.boundingRect(c) for c in contours]) if window: new_rects = [] for rect in segment_rects: dx, dy = 0, 0 new_rect = (rect[0] + x - dx, rect[1] + y - dy, rect[2] + 2 * dx, rect[3] + 2 * dy) new_rects.append(new_rect) segment_rects = new_rects return segment_rects, np.dstack(3 * [display])
def segment_on_dt(img): dt = cv2.distanceTransform(img, 2, 3) # L2 norm, 3x3 mask dt = ((dt - dt.min()) / (dt.max() - dt.min()) * 255).astype(numpy.uint8) dt = cv2.threshold(dt, 100, 255, cv2.THRESH_BINARY)[1] lbl, ncc = label(dt) lbl[img == 0] = lbl.max() + 1 lbl = lbl.astype(numpy.int32) cv2.watershed(cv2.cvtColor(img, cv2.COLOR_GRAY2BGR), lbl) lbl[lbl == -1] = 0 return lbl
def get_keys_from_markers(img, markers_list): #make the markers in the format required by the algorithm h, w = img.shape[:2] markers_array = np.zeros((h, w), np.int32) boundary = 0 for i, mark in enumerate(markers_list): markers_array[mark[1]][mark[0]] = i+1 boundary +=1 cv2.watershed(img, markers_array) return markers_array, boundary
def remove_bg(self): gray = cv2.cvtColor(self.img,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) fg = cv2.erode(thresh,None,iterations = 2) bgt = cv2.dilate(thresh,None,iterations = 3) ret,bg = cv2.threshold(bgt,1,128,1) marker = cv2.add(fg,bg) marker32 = np.int32(marker) cv2.watershed(self.img,marker32) m = cv2.convertScaleAbs(marker32) self.nobg_img = cv2.threshold(m,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1] return self.nobg_img
def method2(self, image): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU) fg = cv2.erode(thresh,None,iterations = 2) bgt = cv2.dilate(thresh,None,iterations = 3) ret,bg = cv2.threshold(bgt,1,128,1) marker = cv2.add(fg,bg) marker32 = np.int32(marker) cv2.watershed(image,marker32) m = cv2.convertScaleAbs(marker32) ret,thresh = cv2.threshold(m,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) res = cv2.bitwise_and(image,image,mask = thresh) return res
def find_optic_disc_watershed(img, P): """ Find optic disk in image using a watershed method. :param img: BGR image :param P: gray image :return: optic_disc, Crs, markers, watershed """ assert img is not None and P is not None #fore = cv2.cvtColor(P,cv2.COLOR_GRAY2BGR) # create watershed data_min, data_body_left, data_body, data_max_left = retina_markers_thresh( P) watershed = np.zeros_like(P).astype("int32") mk_back, mk_body, mk_flare = 1, 2, 3 # background FIXMED use P.min() and aproaching to local maxima watershed[P <= data_min] = mk_back watershed[np.bitwise_and(P > data_body_left, P < data_body)] = mk_body # main body # find bright objects flares_thresh = (P >= data_max_left).astype(np.uint8) contours, hierarchy = findContours( flares_thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) mks_flare = [] for i, cnt in enumerate(contours): index = mk_flare + i mks_flare.append(index) # Flares. this can be used approaching watershed[contours2mask(cnt, shape=watershed.shape)] = index # to local maxima, but brightest areas are almost # always saturated so no need to use it markers = watershed.copy() # apply watershed to watershed # FIXME perhaps the function should be cv2.floodFill? cv2.watershed(img, watershed) # different classification algorithms could be used using watershed contours_flares = [] for mk_flare in mks_flare: brightest = np.uint8(watershed == mk_flare) contours, hierarchy = findContours( brightest, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) contours_flares.extend(contours) Crs = [(i, j) for i, j in [(convexityRatio(cnt), cnt) for cnt in contours_flares] if i != 0] # convexity ratios Crs.sort(reverse=True, key=lambda x: x[0]) candidate = Crs[-1] ellipse = cv2.fitEllipse(candidate[1]) optic_disc = np.zeros_like(P) cv2.ellipse(optic_disc, ellipse, 1, -1) # get elliptical ROI return optic_disc, Crs, markers, watershed
def WATERSHED(Input_Image): ''' Description: Computes watershed segmentation,based on mathematical morphology and flooding of regions from markers. source: openCV parameters: Input_Image : ndarray Input image marker: float return: Segment_mask : ndarray (cols, rows) Integer mask indicating segment labels. ''' # read the input image img = cv2.imread(Input_Image) # convert to grayscale g1 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # smooth the image g = cv2.medianBlur(g1,5) # Apply adaptive threshold thresh1 = cv2.adaptiveThreshold(g,255,1,1,11,2) thresh_color = cv2.cvtColor(thresh1,cv2.COLOR_GRAY2BGR) # Apply dilation and erosion bgt = cv2.dilate(thresh1,None,iterations = 3) fg = cv2.erode(bgt,None,iterations = 2) #thresholding on the background ret,bg = cv2.threshold(bgt,1,128,1) #adding results marker = cv2.add(fg,bg) #moving markers to 32 bit signed single channel marker32 = np.int32(marker) #segmenting cv2.watershed(img,marker32) m = cv2.convertScaleAbs(marker32) ret,thresh = cv2.threshold(m,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) res = cv2.bitwise_and(img,img,mask = thresh) segments_watershed = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY) print("watershed number of segments: %d" % len(np.unique(segments_watershed))) segments_watershed = segments_watershed.astype(np.int32) #print ('segments_watershed datatype',segments_watershed.dtype ) return segments_watershed
def watershed(img, fg_marker): fg_marker = cv2.dilate(fg_marker, None, iterations=5) r, bg_marker = cv2.threshold(cv2.bitwise_not(cv2.dilate(fg_marker, None, iterations=10)), 30, 125, cv2.THRESH_BINARY) marker = cv2.add(fg_marker, bg_marker, dtype=cv2.CV_32SC1) cv2.imwrite('step7-markers.png', marker) color = numpy.zeros((480, 640, 3), numpy.uint8) color[:,:,0] = img color[:,:,1] = img color[:,:,2] = img cv2.watershed(color, marker) cv2.imwrite('step7-watersheds.png', marker) return marker
def watershed_segmentation(bbox, image, rgb_proposal_mask, depth_proposal_mask, bbox_not_moved, watershed_last_frame_seed_mask): # segmentation watershed_mask_seed = create_watershed_seed(bbox, rgb_proposal_mask, bbox_not_moved, watershed_last_frame_seed_mask) watershed_bg_mask = rgb_proposal_mask + depth_proposal_mask # set the background to 1 the luggage pixel to the values found before # the unknown pixel are still 0 #watershed_mask_seed = np.where(watershed_bg_mask == 0, 1, watershed_mask_seed) watershed_mask_seed += 1 # apply watershed - result overwrite in mask cv2.watershed(image, watershed_mask_seed) # OUTPUT MASK FOR FURTHER STUDY return np.where(watershed_mask_seed == 1, 0, 1)
def watershed(img, thresh): # noise removal kernel = np.ones((3,3), np.uint8) opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 4) # sure background area sure_bg = cv2.dilate(opening,kernel,iterations=3) #sure_bg = cv2.morphologyEx(sure_bg, cv2.MORPH_TOPHAT, kernel) # Finding sure foreground area dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0) # Finding unknown region sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg,sure_fg) # Marker labelling ret, markers = cv2.connectedComponents(sure_fg) # Add one to all labels so that sure background is not 0, but 1 markers = markers+1 # Now, mark the region of unknown with zero markers[unknown==255] = 0 ''' imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) imgray = cv2.GaussianBlur(imgray, (5, 5), 0) img = cv2.Canny(imgray,200,500) ''' markers = cv2.watershed(img,markers) img[markers == -1] = [255,0,0] return sure_bg, sure_fg
def water(img, thresh): kernel = np.ones((3,3),np.uint8) opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2) # sure background area sure_bg = cv2.dilate(opening,kernel,iterations=3) # Finding sure foreground area dist_transform = cv2.distanceTransform(opening,2,5) ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0) # Finding unknown region sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg,sure_fg) # Marker labelling ret, markers = cv2.connectedComponents(sure_fg) # Add one to all labels so that sure background is not 0, but 1 markers += 1 # Now, mark the region of unknown with zero markers[unknown==255] = 0 markers = cv2.watershed(img,markers) img[markers == -1] = [255,0,0] return sure_fg, sure_bg, markers, img
def Segmentation(image): height, width = image.shape[0], image.shape[1] temperatureImg = getTemperatureImg(image) averTemperature = temperatureImg.sum() / (height * width) data = cv2.calcHist([temperatureImg], [0], None, [256], [0, 255]) threshold = OSTU(data) _, img = cv2.threshold(temperatureImg, 1.2 * threshold, 255, cv2.THRESH_BINARY) fg = cv2.erode(img, None, iterations = 5) _, img = cv2.threshold(temperatureImg, 0.8 * threshold, 255, cv2.THRESH_BINARY) _, bg = cv2.threshold(cv2.dilate(img, None, iterations = 3), 1, 128, cv2.THRESH_BINARY_INV) marker = cv2.add(fg, bg) markers = np.int32(marker) # in markers 255 is colorfulcolor, 128 is other, -1 is boundary tpImg = np.rollaxis(np.array([temperatureImg] * 3), 0, 3) cv2.watershed(np.array(tpImg, dtype='uint8'), markers) return (markers, temperatureImg)
def watershed2(seem, img): if (img.dtype != np.uint8): img = img * 255 img = np.uint8(img) ut.imgDes(img) img = cv.medianBlur(img, 3) rows, cols = img.shape[:2]; if np.size(img.shape) < 3: img_a = cv.cvtColor(img, cv.COLOR_GRAY2RGB) else: img_a = img print ('ddd') ut.imgDes(img_a) ret, markers = cv.connectedComponents(seem) markers = markers + 1 markers[seem == 0] = 0 markers = cv.watershed(img_a, markers) markers[img==0] = 0 return markers
cv2.circle(markedImg, pt, 9, (colorMark), -1) cv2.circle(scene, pt, 9, colorPallet[colorMark], -1) changedMark = True changedMark = False colorPallet = getColorPallet(10) cv2.namedWindow("img", cv2.WINDOW_AUTOSIZE) cv2.setMouseCallback("img", creatRoots) colorMark = 0 while True: key = cv2.waitKey(1) & 0xFF if key == ord('q'): break elif chr(key).isdigit(): colorMark = eval(chr(key)) print(chr(key), colorMark) if changedMark: copied_markedImg = markedImg.copy() cv2.watershed(srcImg, copied_markedImg) segments = np.zeros_like(srcImg, np.uint8) for clrIndex in range(len(colorPallet)): segments[copied_markedImg == (clrIndex)] = colorPallet[clrIndex] cv2.imshow("img", scene) cv2.imshow("segments", segments) cv2.destroyAllWindows()
def post_process(q=-5): nc_logits = np.squeeze( np.squeeze( np.load(r'E:\MoNUSAC\MyModel\prediction\nc_logits.npy', allow_pickle=True))) nc_target = np.squeeze( np.squeeze( np.load(r'E:\MoNUSAC\MyModel\prediction\nc_target.npy', allow_pickle=True))) np_logits = np.squeeze( np.squeeze( np.load(r'E:\MoNUSAC\MyModel\prediction\np_logits.npy', allow_pickle=True))) hv_logits = np.squeeze( np.load(r'E:\MoNUSAC\MyModel\prediction\hv_logits.npy', allow_pickle=True)) image = np.squeeze( np.load(r'E:\MoNUSAC\MyModel\prediction\image.npy', allow_pickle=True)) image = image.transpose((1, 2, 0)) image2 = image.copy() image2 += 60 * cv2.merge([ np.where(nc_target == 1, 1, 0), np.where(nc_target == 2, 2, 0) + np.where(nc_target == 4, 4, 0), np.where(nc_target == 3, 3, 0) + np.where(nc_target == 4, 4, 0) ]) cv2.imshow('target', image2) # cv2.imshow('h',np.squeeze(hv_logits[0,...]).astype(np.float)) h, v = cv2.Sobel(np.squeeze(hv_logits[0, :, :]), ddepth=-1, dx=1, dy=0, ksize=3), cv2.Sobel(np.squeeze(hv_logits[1, :, :]), ddepth=-1, dx=0, dy=1, ksize=3) # show_('h',h) # show_('v',v) # cv2.imshow('H', h.astype(np.float)) # cv2.imshow('V', v.astype(np.float)) Sm = np.where(h < v, h, v) t = np.argmax(np_logits, axis=0) # t=np_logits # cv2.imshow('sm', Sm.astype(np.float)) # show_('Sm',Sm) tmp = t - np.where(Sm < q, 1, 0) tmp = np.where(tmp > 0, 1, 0) # cv2.imshow('tmp',tmp.astype(np.uint8)*255) sure_bg = 1 - t sure_fg = tmp unkown = 1 - sure_bg - sure_fg _, markers = cv2.connectedComponents(sure_fg.astype(np.uint8)) markers = markers + 1 markers[sure_bg == 1] = 0 # cv2.imshow('mark',markers.astype(np.uint8)) img = cv2.distanceTransform(t.astype(np.uint8), cv2.DIST_L2, cv2.DIST_MASK_3) img = (np.max(img) - img) / (np.max(img) - np.min(img)) * 255 img = img.astype(np.uint8) img = cv2.merge([img, img, img]) # cv2.imshow('img',img) markers = cv2.watershed(img, markers) m = np.zeros((256, 256)) nc_logits = np.argmax(nc_logits, axis=0) for i in np.unique(markers).tolist(): if i > 2: temp = markers.copy() temp = np.where(temp == i, 1, 0) temp = temp * nc_logits maxs = 0 maxc = 0 for j in np.unique(temp).tolist(): if j > 0: temp2 = np.where(temp == j, 1, 0) s = np.sum(temp2) if s > maxs: maxs = s maxc = j m += np.where(markers == i, maxc, 0) image += 60 * cv2.merge([ np.where(m == 1, 1, 0), np.where(m == 2, 2, 0) + np.where(m == 4, 4, 0), np.where(m == 3, 3, 0) + np.where(m == 4, 4, 0) ]) image[markers == -1] = [0, 0, 255] cv2.imshow('img', image) cv2.waitKey(0)
def boundary_refinement_watershed(X, Y_pred, erode=True, save_marks_dir=None): """Apply watershed to the given predictions with the goal of refine the boundaries of the artifacts. Based on https://docs.opencv.org/master/d3/db4/tutorial_py_watershed.html. Parameters ---------- X : 4D Numpy array Original data to guide the watershed. E.g. ``(img_number, x, y, channels)``. Y_pred : 4D Numpy array Predicted data to refine the boundaries. E.g. ``(img_number, x, y, channels)``. erode : bool, optional To extract the sure foreground eroding the artifacts instead of doing with distanceTransform. save_marks_dir : str, optional Directory to save the markers used to make the watershed. Useful for debugging. Returns ------- Array : 4D Numpy array Refined boundaries of the predictions. E.g. ``(img_number, x, y, channels)``. Examples -------- +-----------------------------------------+-----------------------------------------+ | .. figure:: img/FIBSEM_test_0.png | .. figure:: img/FIBSEM_test_0_gt.png | | :width: 80% | :width: 80% | | :align: center | :align: center | | | | | Original image | Ground truth | +-----------------------------------------+-----------------------------------------+ | .. figure:: img/FIBSEM_test_0_pred.png | .. figure:: img/FIBSEM_test_0_wa.png | | :width: 80% | :width: 80% | | :align: center | :align: center | | | | | Predicted image | Watershed ouput | +-----------------------------------------+-----------------------------------------+ The marks used to guide the watershed is this example are these: .. image:: img/watershed2_marks_test0.png :width: 70% :align: center """ if save_marks_dir is not None: os.makedirs(save_marks_dir, exist_ok=True) watershed_predictions = np.zeros(Y_pred.shape[:3]) kernel = np.ones((3, 3), np.uint8) d = len(str(X.shape[0])) for i in tqdm(range(X.shape[0])): im = cv2.cvtColor(X[i, ...] * 255, cv2.COLOR_GRAY2RGB) pred = Y_pred[i, ..., 0] # sure background area sure_bg = cv2.dilate(pred, kernel, iterations=3) sure_bg = np.uint8(sure_bg) # Finding sure foreground area if erode: sure_fg = cv2.erode(pred, kernel, iterations=3) else: dist_transform = cv2.distanceTransform(a, cv2.DIST_L2, 5) ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0) sure_fg = np.uint8(sure_fg) # Finding unknown region unknown_reg = cv2.subtract(sure_bg, sure_fg) # Marker labelling ret, markers = cv2.connectedComponents(sure_fg) # Add one to all labels so that sure background is not 0, but 1 markers = markers + 1 # Now, mark the region of unknown with zero markers[unknown_reg == 1] = 0 if save_marks_dir is not None: f = os.path.join(save_marks_dir, "mark_" + str(i).zfill(d) + ".png") cv2.imwrite(f, markers) markers = cv2.watershed((im).astype(np.uint8), markers) watershed_predictions[i] = markers # Label all artifacts into 1 and the background with 0 watershed_predictions[watershed_predictions == 1] = 0 watershed_predictions[watershed_predictions > 1] = 1 watershed_predictions[watershed_predictions == -1] = 0 return np.expand_dims(watershed_predictions, -1)
cv2.namedWindow('Road Image') cv2.setMouseCallback('Road Image', mouse_callback) while True: cv2.imshow('Watershed Segments', segments) cv2.imshow('Road Image', road_copy) k = cv2.waitKey(1) if k == 27: break elif k == ord('c'): road_copy = road.copy() marker_image = np.zeros(road.shape[:2], dtype=np.int32) segments = np.zeros(road.shape, dtype=np.uint8) elif k > 0 and chr(k).isdigit(): current_marker = int(chr(k)) if marks_updated: marker_image_copy = marker_image.copy() cv2.watershed(road, marker_image_copy) segments = np.zeros(road.shape, dtype=np.uint8) for color_ind in range(n_markers): segments[marker_image_copy == (color_ind)] = colors[color_ind] marks_updated = False cv2.destroyAllWindows()
sx = np.min(ind[0]) - border_width ex = np.max(ind[0]) + border_width sy = np.min(ind[1]) - border_width ey = np.max(ind[1]) + border_width # distance transform one_comp = oldmarkers[sx:ex, sy:ey] == i compon_dis = cv2.distanceTransform(one_comp.astype(np.uint8), cv2.DIST_L2, 5) _, dis_peak = cv2.threshold(compon_dis, 0.75 * compon_dis.max(), 255, 0) # watershed ret, new_markers = cv2.connectedComponents(dis_peak.astype(np.uint8)) new_markers = new_markers + 1 new_markers[(one_comp == True) & (new_markers == 1)] = 0 water = cv2.watershed(img[sx:ex, sy:ey], new_markers.copy()) # draw for j in range(2, ret + 1): c = cv2.findContours(np.uint8(water == j), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1] if len(c): c = c[0] else: continue c[:, 0, 0] += sy c[:, 0, 1] += sx # cv2.drawContours(img, [c], -1, (0, 0, 255), 5) mm = 20 minx = np.min(c[:, 0, 0]) - mm maxx = np.max(c[:, 0, 0]) + mm
D2 = ndi.distance_transform_edt(fat_markers) dist_binary2 = D2 > dt_t dist_binary2 = dist_binary2.astype(np.float) # plt.figure();plt.imshow(dist_binary2) dist_binary2_ = morphology.remove_small_holes( util.pad(dist_binary2, (1, ), 'constant', constant_values=0).astype(np.int), 300) dist_binary2_ = dist_binary2_[1:-1, 1:-1] # plt.figure();plt.imshow(dist_binary2_) sure_fg = dist_binary1_.astype(np.float) * dist_binary2_.astype(np.float) sure_fgo = morphology.binary_opening(sure_fg, morphology.disk(5)) unknown = np.maximum(sure_bg - sure_fgo, 0) markers = measure.label(sure_fgo, background=0) markers += 1 markers[unknown == 1] = 0 # plt.figure();plt.imshow(markers, cmap=cmap) imgc_ = np.uint8(imgc * 255.) labels = cv2.watershed(imgc_, markers) plt.figure() plt.imshow(labels.get(), cmap=cmap) imgc_overlay = imgc imgc_overlay[labels.get() == -1] = [1, 0, 0] plt.figure() plt.imshow(imgc_overlay) #######################################################################
fg = compare(road_lbp, sample=(880, 100), high=64, width=32, condi=0.84) # print(np.unique(fg, return_counts=True)) cv2.imshow("fg", fg) # watershed blur = cv2.GaussianBlur(gray, (5, 5), 0) _, thres = cv2.threshold(blur, 0, 255, cv2.THRESH_OTSU+cv2.THRESH_BINARY_INV) kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) mb = cv2.morphologyEx(thres, cv2.MORPH_OPEN, kernel, iterations=2) bg = cv2.dilate(mb, kernel, iterations=3) # cv2.imshow("bg", bg) unknown = cv2.subtract(bg, fg) _, markers = cv2.connectedComponents(fg) # print(np.unique(markers, return_counts=True)) markers = cv2.watershed(road, markers=markers) # markers = markers + 1 # markers[unknown == 255] = 4 road[markers == -1] = [0, 0, 0] # print(road[markers == 1]) # cv2.imshow("watershed", road) # draw color_block = np.zeros(road.shape, dtype=np.uint8) color_block[markers == 0] = [255, 255, 255] color_block[markers == 1] = [191, 62, 255] color_block[markers == 2] = [130, 130, 130] color_block[markers == 3] = [152, 251, 152] # cv2.imshow("color_block", color_block) # result
def getWatershed(data, w): height = np.array(data) image = np.zeros(height.shape) for i in range(len(data)): for j in range(len(data[0])): height[i][j] = data[i][j].elevation maximum = np.amax(height) minimum = np.amin(height) numberOfBits = 16 interval = (maximum - minimum) / (pow(2, numberOfBits) - 1) for i in range(len(height)): for j in range(len(height[0])): image[i][j] = int(data[i][j].getRisk(minimum, maximum) * (pow(2, numberOfBits) - 1)) image = image.astype('uint8') * 255 cv2.imshow("w", resizeimage(image, 1000)) cv2.waitKey(0) # image = cv2.bitwise_not(image) # image = resizeimage(image, 1000) image3 = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB) ret, thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # noise removal kernel = np.ones((3, 3), np.uint8) # sure background area sure_bg = cv2.dilate(thresh, kernel, iterations=3) # Finding sure foreground area dist_transform = cv2.distanceTransform(thresh, cv2.DIST_L2, 5) ret, sure_fg = cv2.threshold(dist_transform, 0.3 * dist_transform.max(), 255, 0) # Finding unknown region sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg, sure_fg) # Marker labelling ret, markers = cv2.connectedComponents(sure_fg) # Add one to all labels so that sure background is not 0, but 1 markers = markers + 1 # Now, mark the region of unknown with zero markers[unknown == 255] = 0 markers = cv2.watershed(image3, markers) diff = [] for m in markers: for a in m: if not a in diff: diff.append(a) image3[markers == -1] = [255, 0, 0] # Map to store region wise location objects regions = getRegions(markers, data) # Map to store region boundary location objects regionBoundary = findboundary2(markers, data) # Map to store regions and there relative sizes sizeFactor = {} # Size list sizeList = {} # Map to Store Average Depths avgDepth = {} # Map to store the centers of the regions centers = {} maxSize = 0 for k in regions: # Find maximum size region if k not in sizeFactor: sizeFactor[k] = float(len(regions[k])) maxSize = max(maxSize, sizeFactor[k]) sizeList[k] = len(regions[k]) # Find the center of the region i,e, the minimum depth region minDepth = regions[k][0] # Depth wise classification depthSum = 0 for val in regions[k]: if minDepth.elevation > val.elevation: minDepth = val depthSum = depthSum + val.elevation centers[k] = minDepth # Normalise the depth avgDepth[k] = depthSum / len(regions[k]) # Normalize the size factors with respect to greatest size region for k in sizeFactor: sizeFactor[k] = sizeFactor[k] / maxSize maxDepth = avgDepth[list(avgDepth.keys())[0]] for k in avgDepth: maxDepth = max(maxDepth, avgDepth[k]) for k in avgDepth: avgDepth[k] = avgDepth[k] / maxDepth factor1 = 0.5 factor2 = 0.5 riskFactor = {} for k in regions: riskFactor[k] = factor1 * (1 - avgDepth[k]) + factor2 * sizeFactor[k] riskObjects = [] rs = [] for k in regions: if k == -1: continue risk = riskFactor[k] area = pow((pow(sizeList[k], 0.5) * w) / 1000, 2) riskObjects.append( RiskMapRegion(centers[k], regionBoundary[k], risk, area)) # rs.append((-risk, -area, k)) # rs.sort() # rss = rs[:w] # rb = {} # for r in rss: # rb[r[2]] = regionBoundary[r[2]] # print("YO") # sb = sort_boundaries(rb, data) # for r in rss: # riskObjects.append(RiskMapRegion(centers[r[2]],sb[r[2]],risk,area)) return sorted(riskObjects, key=func)
def find_contours(image): # Conversion to HSV space and taking the saturation channel hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV) img = cv.split(hsv)[1] # cv.imwrite("0_saturation.png", img) # Thresholding _, dst = cv.threshold(img, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU) # cv.imwrite("1_thresholded.png", dst) # Mask borders b_mask = borders_mask(image) # cv.imwrite("2_borders_mask.png", b_mask) dst = cv.bitwise_and(dst, b_mask) # Finding contours to remove holes contours, _ = cv.findContours(dst, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE) # tmp = np.zeros((400, 600), dtype=np.uint8) # cv.drawContours(tmp, contours, -1, (255, 255, 255), -1, 4) # cv.imwrite("3_unfiltered_cc.png", tmp) final = None final_ref = 1.0 for c in contours: area = cv.contourArea(c) perimeter = cv.arcLength(c, True) circ = circularity(area, perimeter) if area > 400 and circ < 0.8: if area > final_ref: final = c final_ref = area mask = np.zeros((400, 600), dtype=np.uint8) if final is not None: cv.drawContours(mask, [final], -1, (255, 255, 255), -1, 4) # cv.imwrite("4_final_mask.png", mask) ### WATERSHED START ## FOREGROUND # Distance transform and thresholding fg = cv.distanceTransform(mask, cv.DIST_L2, cv.DIST_MASK_PRECISE) fg_min = np.amin(fg) fg_max = np.amax(fg) fg[:] = (fg - fg_min) * 255 // (fg_max - fg_min) fg = np.uint8(fg) _, fg = cv.threshold(fg, 100, 255, cv.THRESH_BINARY) ## BACKGROUND bg = cv.dilate(mask, None, iterations=4) bg[bg == 0] = 128 bg[bg == 255] = 0 ## MARKERS markers = cv.add(fg, bg) # cv.imwrite("5_watershed_mask.png", markers) markers32 = np.int32(markers) cv.watershed(image, markers32) w_mask = cv.convertScaleAbs(markers32) # cv.imwrite("6_watershed_mask.png", w_mask) w_mask[w_mask == 128] = 0 w_mask[w_mask == 1] = 255 w_mask[0, :] = 0 w_mask[w_mask.shape[0] - 1, :] = 0 w_mask[:, 0] = 0 w_mask[:, w_mask.shape[1] - 1] = 0 # cv.imwrite("7_final_result.png", w_mask) return w_mask
def bottleCapDetect(img): scale_factor = min(1024 / img.shape[0], 768 / img.shape[1], 1) img = cv2.resize(img, (0, 0), fx=scale_factor, fy=scale_factor) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) edge_threshold = 10 edeg_threahold_max = 2 * edge_threshold blurred = cv2.medianBlur(gray, 3) edges = cv2.Canny(blurred, edge_threshold, edeg_threahold_max, apertureSize=3) struct_ele = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)) edges_closed = edges.copy() edges_closed = cv2.morphologyEx(edges_closed, cv2.MORPH_DILATE, struct_ele, iterations=1) edges_closed = cv2.morphologyEx(edges_closed, cv2.MORPH_CLOSE, struct_ele, iterations=5) mask = np.zeros((edges_closed.shape[0] + 2, edges_closed.shape[1] + 2), dtype="uint8") cv2.floodFill(edges_closed, mask, (0, 0), 255, flags=cv2.FLOODFILL_MASK_ONLY)[1] mask[...] = 255 * (1 - mask) cap_cnt = 10 def get_markers(mask_orig): mask = mask_orig.copy() cnt = 0 result = [] while cnt < cap_cnt: mask = cv2.medianBlur(mask, 9) # do distance transform dist = cv2.distanceTransform(mask, cv2.DIST_L2, 5) dist = dist.astype("uint8") ret, markers_binary = cv2.threshold(dist, 0.8 * dist.max(), 255, 0) # do marker labelling ret, markers = cv2.connectedComponents(markers_binary) cur_cnt = markers.max() print("Got", cur_cnt, "marker(s)") cnt += cur_cnt cur_result = [] for i in range(1, cur_cnt + 1): pos = np.nonzero(markers == i) x, y = pos[1], pos[0] minx, maxx, miny, maxy = x.min(), x.max(), y.min(), y.max() w = np.max(dist[markers == i]) cur_result.append(((minx, miny), (maxx, maxy), w)) result.extend(cur_result) if cnt < cap_cnt: for i in range(cur_cnt): (minx, miny), (maxx, maxy), w = cur_result[i] radius = w + 20 # just in case :) print("Removing", (minx, miny), (maxx, maxy), radius) mask = cv2.circle(mask, ((minx + maxx) // 2, (miny + maxy) // 2), radius, 0, -1) elif cnt > cap_cnt: print("warning: 翻车啦") return result markers = get_markers(mask) # now prepare for watersheding ws = np.logical_not(mask).astype('int32') for i, (p1, p2, w) in enumerate(markers): center = (p1[0] + p2[0]) // 2, (p1[1] + p2[1]) // 2 axis = ((p2[0] - p1[0]) // 2, (p2[1] - p1[1]) // 2) cv2.ellipse(ws, center, axis, 0, 0, 360, i + 2, cv2.FILLED) flooded = ws.copy() flooded = cv2.watershed(cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR), flooded) flooded[...] = flooded - 1 flooded[flooded <= 0] = 0 # dilate a little to remove tiny edges flooded = flooded.astype("uint8") flooded = cv2.morphologyEx(flooded, cv2.MORPH_DILATE, struct_ele, iterations=1) ws = flooded boxed = img.copy() bounding_boxes = [] minimal_bounding_boxes = [] for i in range(cap_cnt): # value in marker image is i+1 buf = (ws == i + 1).astype('uint8') contours, hierarchy = cv2.findContours(buf, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) assert (len(contours) == 1) x, y, w, h = cv2.boundingRect(contours[0]) bounding_boxes.append(((x, y), (x + w, y + h))) minimal_bounding_boxes.append(cv2.minAreaRect(contours[0])) ellipse = cv2.fitEllipse(contours[0]) cv2.ellipse(boxed, ellipse, (0, 255, 0), 2) box_points = cv2.boxPoints(minimal_bounding_boxes[-1]) box_points = np.int0(box_points) cv2.rectangle(boxed, bounding_boxes[-1][0], bounding_boxes[-1][1], (255, 0, 0), 2) cv2.drawContours(boxed, [box_points], 0, (0, 0, 255), 2) real_caps = [] cap_edges = [] real_ans = [] cord = [] edges = cv2.Canny(img, 40, 80) for i, ((p1, p2), (center, (width, height), a)) in enumerate(zip(bounding_boxes, minimal_bounding_boxes)): g = gray[p1[1]:p2[1], p1[0]:p2[0]] e = edges[p1[1]:p2[1], p1[0]:p2[0]] cord.append(center) if width / height > 1.5 or height / width > 1.5: print(i, "is a side") real_ans.append('side') else: real_ans.append(None) # do circle approximation for better center mounting circles = cv2.HoughCircles(g, cv2.HOUGH_GRADIENT, 2, 40, 1, 20, 40, 200) if type(circles[0][0]) == np.ndarray: for i in circles[0, :]: # draw the outer circle cv2.circle(g, (i[0], i[1]), i[2], 255, 2) # draw the center of the circle cv2.circle(g, (i[0], i[1]), 2, 255, 3) real_caps.append(g) cap_edges.append(e) k = len(real_caps) t = cv2.getGaussianKernel(9, 1) gaussian_kernel = t * t.T gaussian_kernel *= 255 / np.max(gaussian_kernel) gaussian_kernel = np.uint8(gaussian_kernel) gaussian_kernel = cv2.resize(gaussian_kernel, (64, 64)) for no, (cap, edge) in enumerate(zip(real_caps, cap_edges)): if real_ans[no] is not None: print("Skipping", no, "it is a side") continue c = cv2.resize(cap, (128, 128)) e = cv2.resize(edge, (128, 128)) rx, ry = c.shape[0] // 4, c.shape[1] // 4 cx, cy = c.shape[0] // 2, c.shape[1] // 2 score = np.sum(e[cx - rx:cx + rx, cy - ry:cy + ry] * gaussian_kernel) print(score) real_ans[no] = 'top' if score > 50000 else 'tail' labelled = img.copy() for i in range(len(real_ans)): if real_ans[i] == 'top': color = (255, 0, 0) elif real_ans[i] == 'tail': color = (0, 255, 0) else: color = (0, 0, 255) cv2.rectangle(labelled, bounding_boxes[i][0], bounding_boxes[i][1], color, 2) cv2.putText(labelled, real_ans[i], bounding_boxes[i][0], cv2.FONT_HERSHEY_SIMPLEX, 1, color, 2) cv2.putText(labelled, "({},{})".format(int(cord[i][0]), int(cord[i][1])), (int(cord[i][0]) - 50, int(cord[i][1])), cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 2) return labelled
def segment_by_watershed( binary_img: np.ndarray, img: np.ndarray, dist_thresh: float = 3.0) -> Tuple[np.ndarray, List[np.ndarray]]: """Segment image using watershed algorithm. Parameters ---------- binary_img:np.ndarray Binary image derived from ``img`` with nonzero pixel blobs for objects. This is usually produced after converting the ``img`` to grayscale and then thresholding. img: np.ndarray Original image to be segmented. dist_thresh: float, optional Threshold for distance of pixels from boundary to consider them core points. If it is < 1.0, it is interpreted as fraction of the maximum of the distances. Returns ------- points_list: list[np.ndarray] List of arrays containing positions of the pixels in each object. Notes ----- This code is derivative of this OpenCV tutorial: https://docs.opencv.org/master/d3/db4/tutorial_py_watershed.html and falls under the same licensing. """ kernel = np.ones((3, 3), dtype=np.uint8) opening = cv2.morphologyEx(binary_img, cv2.MORPH_OPEN, kernel, iterations=2) # Distance transform calculates the distance of each pixel from # background (black in this case) pixels. So we have an image # where pixel intensity means the distance of that pixel from the # background dist_xform = cv2.distanceTransform(opening, cv2.DIST_L2, cv2.DIST_MASK_PRECISE) # Thresholding the distance image to find pixels which are more # than a certain distance away from background - this should give # us the pixels central to foreground objects if dist_thresh < 1.0: # threshold relative to maximum of computed distance dist_thresh *= dist_xform.max() ret, sure_fg = cv2.threshold(dist_xform, dist_thresh, 255, 0) sure_fg = np.uint8(sure_fg) # border between background and foreground sure_bg = cv2.dilate(opening, kernel, iterations=3) unknown = cv2.subtract(sure_bg, sure_fg) ret, markers = cv2.connectedComponents(sure_fg, connectivity=4) # logging.debug(f'Found {ret} connected components') # 0 is for background - assign a large value to keep them off markers += 1 markers[unknown == 255] = 0 markers = cv2.watershed(img, markers) unique_labels = set(markers.flat) unique_labels.discard(-1) unique_labels.discard(0) ret = [np.argwhere(markers == label) for label in sorted(unique_labels)] # markers[markers == -1] = 0 # markers = np.uint8(markers) # Fast swapping of y and x - see answer by blax here: # https://stackoverflow.com/questions/4857927/swapping-columns-in-a-numpy-array for points in ret: points[:, 0], points[:, 1] = points[:, 1], points[:, 0].copy() return ret
def get_track(img): """ Creates and returns a binary image of the track. Also finds track sections and starts the calculation of the racing line :param img: the image :return: a binary image of the track """ # Set the bounds to detect the black parts of the track and invert it to get the actual track lower_bounds_track = np.array([0, 0, 0]) upper_bounds_track = np.array([10, 10, 10]) track = cv.bitwise_not( cv.inRange(img, lower_bounds_track, upper_bounds_track)) # Closing (Dilate + Erode) to remove noise (of the ball border) track = cv.morphologyEx(track, cv.MORPH_CLOSE, np.ones((5, 5), np.uint8)) # Find the finish line lower_bounds_finish = np.array([200, 100, 0]) upper_bounds_finish = np.array([255, 150, 10]) finish_line = cv.dilate(cv.inRange(img, lower_bounds_finish, upper_bounds_finish), np.ones((5, 5), np.uint8), iterations=1) finish_line_coords = cv.findNonZero(finish_line) finish_line_center = np.mean(finish_line_coords, axis=0)[0] # Get the contours of the track _, contours, _ = cv.findContours(track, cv.RETR_TREE, cv.CHAIN_APPROX_NONE) image = track.copy() # Get the inner and outer contour and the indices of the points where they touch the finish line inner_contour, outer_contour, inner_start_index, outer_start_index, inner_contour_index = _get_inner_and_outer_contour( contours, finish_line_coords) # Calculate the starting direction based on the center of the actual start line and center of the orange area direction = finish_line_center - MatrixOps.convex_combination( inner_contour[inner_start_index], outer_contour[outer_start_index], 0.5) direction = direction / MatrixOps.fast_norm(direction) ### Calculate cross sections of the track ### # Create empty/black 3-channel image to run watershed on img_empty = np.zeros(img.shape, np.uint8) # Create a 1-channel image for the markers markers = np.zeros(image.shape, np.int32) # Mark the inner contour with label 1 and the other contours with label 2 by drawing them on the markers image for i in range(0, len(contours)): cv.drawContours(markers, contours, i, 1 if i == inner_contour_index else 2) # Use watershed to get the boundary between inner and outer contour markers = cv.watershed(img_empty, markers) # Remove '-1' markers on the border of the image markers[:, 0] = markers[1, 1] markers[0, :] = markers[1, 1] markers[:, -1] = markers[1, 1] markers[-1, :] = markers[1, 1] # Get a sorted vector of all positions of points on the watershed border _, watershed_contours, _ = cv.findContours( (markers == -1).astype(np.uint8), cv.RETR_TREE, cv.CHAIN_APPROX_NONE) watershed_contour = watershed_contours[0].reshape( len(watershed_contours[0]), 2) img[markers == -1] = [0, 0, 255] # cv.imshow("color", img) TODO remove # # Circshift the contour so that the first point corresponds to the start/finishing line start_index = MatrixOps.find_closest_point_index( MatrixOps.convex_combination(inner_contour[inner_start_index], outer_contour[outer_start_index], 0.5), watershed_contour) watershed_contour = np.roll(watershed_contour, -2 * start_index) # Check if flipping the contour array is necessary based on the start direction next_point = watershed_contour[0] + direction closest_point_index = MatrixOps.find_closest_point_index( next_point, watershed_contour[[1, len(watershed_contour) - 1]]) if closest_point_index == 1: watershed_contour = np.flip(watershed_contour, 0) # Reduce the number of points on the contour to get the checkpoints needed for smoothing and for the features checkpoints = watershed_contour[::20] #for c in checkpoints: # cv.circle(image, tuple(c), 3, (192, 192, 192), -1) #cv.imshow("image", image) # Erode the track/dilate the track border by the radius of the ball kernel = np.ones((5, 5), np.uint8) eroded_track = cv.erode( image, kernel, iterations=4 ) # Kernel increases border by 2 pixel each iteration, ball seems to have a radius of about 8 pixels #cv.imshow("eroded_track", eroded_track) TODO remove # smoothened_checkpoints = _smoothen_checkpoints_contour( checkpoints, eroded_track) #for c in smoothened_checkpoints: # cv.circle(image, tuple(c), 3, (192, 192, 192), -1) #cv.imshow("image", image) return track, smoothened_checkpoints
DistNorm = np.uint8(DistImg * C) cv2.imshow('DistNorm', DistNorm) _, DistBin = cv2.threshold(src=DistNorm, thresh=DistNorm.max() * 0.7, maxval=255, type=cv2.THRESH_BINARY) cv2.imshow('DistBin', DistBin) # cv2.imshow('DistImg', cv2.normalize(src=DistImg, norm_type=cv2.NORM_MINMAX)) # unknown # Unknown = DilationImg - DistBin Unknown = cv2.subtract(DilationImg, DistBin) cv2.imshow('Unknown', Unknown) # connect MarkImg = np.zeros(GrayImg.shape, dtype=np.int32) MarkImg[DilationImg == 0] = 1 ForegroundContours, _ = cv2.findContours(image=DistBin.copy(), mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_NONE) ret, MarkImg = markContours(ForegroundContours, markImg=MarkImg, startNum=2) cv2.imshow('MarkImg', np.uint8(MarkImg * (255.0 / MarkImg.max()))) cv2.watershed(SrcImg, MarkImg) SrcImg[MarkImg == -1] = [0, 0, 255] cv2.imshow('Src', SrcImg) cv2.imshow('Gray', GrayImg) cv2.imshow('Bin', BinImg) cv2.waitKey()
def textDetectWatershed(thresh, original, draw=False, group=False): """ Text detection using watershed algorithm """ # According to: http://docs.opencv.org/trunk/d3/db4/tutorial_py_watershed.html img = resize(original, 3000) thresh = resize(thresh, 3000) # noise removal kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=3) # sure background area sure_bg = cv2.dilate(opening, kernel, iterations=3) # Finding sure foreground area dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) ret, sure_fg = cv2.threshold(dist_transform, 0.001 * dist_transform.max(), 255, 0) # Finding unknown region sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg, sure_fg) # Marker labelling ret, markers = cv2.connectedComponents(sure_fg) # Add one to all labels so that sure background is not 0, but 1 markers += 1 # Now, mark the region of unknown with zero markers[unknown == 255] = 0 markers = cv2.watershed(img, markers) image = img.copy() gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Creating result array boxes = [] for mark in np.unique(markers): # mark == 0 --> background if mark == 0: continue # Draw it on mask and detect biggest contour mask = np.zeros(gray.shape, dtype="uint8") mask[markers == mark] = 255 cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] c = max(cnts, key=cv2.contourArea) # Draw a bounding rectangle if it contains text x, y, w, h = cv2.boundingRect(c) cv2.drawContours(mask, c, 0, (255, 255, 255), cv2.FILLED) maskROI = mask[y:y + h, x:x + w] # Ratio of white pixels to area of bounding rectangle r = cv2.countNonZero(maskROI) / (w * h) # Limits for text if r > 0.1 and 2000 > w > 15 and 1500 > h > 15: boxes += [[x, y, w, h]] # Group intersecting rectangles if group: boxes = group_rectangles(boxes) boxes.sort(key=lambda b: (b[1] + b[3], b[0])) bounding_boxes = np.array([0, 0, 0, 0]) rois = [] for (x, y, w, h) in boxes: rois.append(img[y:y + h, x:x + w]) cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) bounding_boxes = np.vstack( (bounding_boxes, np.array([x, y, x + w, y + h]))) if draw: implt(sure_bg, t='sure_background') implt(sure_fg, t='sure_foreground') implt(unknown, t='unknown area') implt(markers, t='Markers') implt(image) # Recalculate coordinates to original size boxes = bounding_boxes[1:].dot(ratio(original, img.shape[0])).astype(np.int64) return boxes, rois
def process(filename, output_folder, verbose): img = cv.imread(filename) grayscale = cv.imread(filename, 0) filename = os.path.basename(filename).split('.')[-2] # Edge enchancement unsharp = unsharp_mask(grayscale, amount=6, threshold=0) bilateral_blur = cv.bilateralFilter(unsharp, 9, 75, 75) _, th = cv.threshold(bilateral_blur, 0, 255, cv.THRESH_BINARY+cv.THRESH_OTSU) # Noise reduction kernel = np.ones((3,3), np.uint8) m_blur = cv.medianBlur(cv.medianBlur(th, 3), 3) opening = cv.morphologyEx(m_blur, cv.MORPH_OPEN, kernel, iterations = 1) # Watershed segmentation sure_bg = cv.dilate(opening, kernel, iterations=2) dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 0) dist_transform = cv.normalize(dist_transform, dist_transform, 0, 255, cv.NORM_MINMAX) _, sure_fg = cv.threshold(dist_transform, 0.23 * dist_transform.max(), 255, 0) sure_fg = np.uint8(sure_fg * 100000) unknown = cv.subtract(sure_bg, sure_fg) _, markers = cv.connectedComponents(sure_fg) markers = markers + 1 markers[unknown==255] = 0 markers = cv.watershed(img, markers) bordered = opening bordered[markers == -1] = 0 bordered = cv.convertScaleAbs(bordered) bordered = cv.erode(bordered, kernel, iterations=1) # Contour detection contours, hierarchy = cv.findContours(bordered, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) contours = [c for c in contours if cv.contourArea(c)>5] # Filtering erroneous contours (with tiny areas) moments = [cv.moments(c) for c in contours] centroids = [(int(m['m10']/m['m00']), int(m['m01']/m['m00'])) for m in moments] # Scaling contours up (to revert errosion effect) contours = [np.asarray(((c - cent)*1.05)+cent, int) for c, cent in zip(contours, centroids)] result = cv.cvtColor(grayscale, cv.COLOR_GRAY2RGB) cv.drawContours(result, contours, -1, (0,255,0), thickness=1, lineType=cv.LINE_AA) contours_filled = np.zeros(grayscale.shape) cv.fillPoly(contours_filled, pts=contours, color=(255,255,255)) # Calculation of equivalent diameter equivalent_diameters = [np.sqrt(4 * m['m00'] / np.pi) for m in moments] max_ = max(equivalent_diameters) min_ = min(equivalent_diameters) contours_colored = cv.cvtColor(grayscale, cv.COLOR_GRAY2RGB) for c, d in zip(contours, equivalent_diameters): color = (int(255*(d-min_)/(max_-min_)), 0, int(255-255*(d-min_)/(max_-min_))) cv.drawContours(contours_colored, [c], -1, color, thickness=2, lineType=cv.LINE_AA) colormap = colors.LinearSegmentedColormap.from_list("BuRd", [(0,0,1), (1,0,0)], 256) plt.figure(figsize=(10,10)) plt.axis('off') plt.title('Particles colored with respect to equivalent diameter.') plt.imshow(contours_colored, colormap) cbar = plt.colorbar(fraction=0.0455, pad=0.04) interp = lambda x: (int(x)*(max_-min_)+255*min_)//255 cbar.ax.set_yticklabels([interp(l.get_text()) for l in cbar.ax.get_yticklabels()]) plt.savefig(output_folder+filename+'_contours_colored.png', dpi=200) # Size distribution plt.figure(figsize=(10,3)) plt.title('Particle size distribution.') nums, bins, patches = plt.hist(equivalent_diameters, bins=16) bins /= max(bins) for b, p in zip(bins, patches): plt.setp(p, 'facecolor', colormap(b)) plt.savefig(output_folder+filename+'_size_distribution.png', dpi=150) cv.imwrite(output_folder+filename+'_contours_filled.png', contours_filled) if verbose: cv.imwrite(output_folder+filename+'_unsharp.png', unsharp) cv.imwrite(output_folder+filename+'_th.png', th) cv.imwrite(output_folder+filename+'_opening.png', opening) cv.imwrite(output_folder+filename+'_sure_bg.png', sure_bg) cv.imwrite(output_folder+filename+'_dist_transform.png', dist_transform) cv.imwrite(output_folder+filename+'_sure_fg.png', sure_fg) cv.imwrite(output_folder+filename+'_unknown.png', unknown) cv.imwrite(output_folder+filename+'_markers.png', markers) cv.imwrite(output_folder+filename+'_contours.png', result)
foreground = foreground.astype(np.uint8) #label是标签,该函数把图像背景标成0,其他封闭目标用从1开始的整数标记 #stats 是bounding box的信息,N*5的矩阵,行对应每个label,五列分别为[x0, y0, 宽度, 高度, 面积] #centroids 是每个域的质心坐标 _, labels, stats, centroids = cv2.connectedComponentsWithStats(foreground) #使背景标记为1 labels = labels + 1 ax4 = fig.add_subplot(164) ax4.imshow(labels) ax4.set_title("foreground") #确定的前景目标标记为2、3、4......(不同目标标记为不同序号,方面后面进行粘连前景的分割) markers[np.where(labels != 1)] = labels[np.where(labels != 1)] markers2 = markers.copy() ax5 = fig.add_subplot(165) ax5.imshow(markers) ax5.set_title("markers") #只接受三通道的图像 #分水岭变换的结果会保存在markers2中 cv2.watershed(img, markers2) ax6 = fig.add_subplot(166) ax6.imshow(markers2) ax6.set_title("obj") plt.show()
def contours_watershed_filter(frame, contours): list_final_Contourn = [] frame_height, frame_width = frame.shape[:2] i = 0 for cnt in contours: black_frame = np.zeros((frame_height, frame_width, 1), dtype="uint8") cv2.drawContours(black_frame, [cnt], 0, 255, -1) x_rect, y_rect, w, h = cv2.boundingRect(cnt) x_prec = int(round(x_rect - (w / 2))) x2_prec = x_prec + (2 * w) y_prec = int(round(y_rect - (h / 2))) y2_prec = y_prec + (2 * h) height, width = frame.shape[:2] x = 0 if x_prec < 0 else x_prec y = 0 if y_prec < 0 else y_prec x2 = width - 1 if x2_prec > width - 1 else x2_prec y2 = height - 1 if y2_prec > height - 1 else y2_prec imCrop = frame[y:y2, x:x2] cropCopy = imCrop.copy() mask_crop = black_frame[y:y2, x:x2] kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(mask_crop, cv2.MORPH_OPEN, kernel, iterations=1) sure_bg = cv2.dilate(opening, kernel, iterations=5) sure_fg = np.uint8(opening) unknown = cv2.subtract(sure_bg, sure_fg) ret, markers = cv2.connectedComponents(sure_fg) markers = markers + 1 markers[unknown == 255] = 0 markers = cv2.watershed(cropCopy, markers) markers[:, 0] = 1 markers[0, :] = 1 markers[-1, :] = 1 markers[:, -1] = 1 cropCopy[markers == -1] = [255, 0, 0] black_little_frame = np.zeros((y2 - y, x2 - x), np.uint8) black_little_frame[markers == -1] = 255 contours_little, hieracy = cv2.findContours(black_little_frame, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) img_contours_little = np.zeros( (black_little_frame.shape[0], black_little_frame.shape[1], 1), dtype="uint8") cv2.drawContours(img_contours_little, contours_little, -1, 255, -1) momenti = cv2.moments(img_contours_little, True) c = ((momenti['m00'])**2) / (2 * math.pi * (momenti['mu20'] + momenti['mu02'])) if c >= 0.95: hu_moments = cv2.HuMoments(momenti).flatten() list_final_Contourn.append(cnt) i += 1 return list_final_Contourn
def crop_img(img, indx, done=False): if done is False: plt.imshow(img) plt.show() #sets the background of the image to black mask = np.zeros(img.shape[:2], np.uint8) bgdModel = np.zeros((1, 65), np.float64) fgdModel = np.zeros((1, 65), np.float64) rect = (50, 50, 450, 290) cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT) mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8') img = img * mask2[:, :, np.newaxis] plt.imshow(img) #plt.show() #picks out a specific object in the image and crops out everything but that #code from opencv's website on watershed gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) ret, thresh = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # noise removal kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2) # sure background area sure_bg = cv2.dilate(opening, kernel, iterations=3) # Finding sure foreground area dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0) # Finding unknown region sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg, sure_fg) # Marker labelling ret, markers = cv2.connectedComponents(sure_fg) # Add one to all labels so that sure background is not 0, but 1 markers = markers + 1 # Now, mark the region of unknown with zero markers[unknown == 255] = 0 markers = cv2.watershed(img, markers) img[markers == -1] = [255, 255, 255] loc = [] plt.imshow(img) plt.show() #performs the cropping of the image for i in range(len(markers)): for j in range(len(markers[i])): if markers[i][j] == 1: loc.append((i, j)) if len(loc) > 1: loc.pop(0) x = [] for i in range(len(loc)): x.append(loc[i][0]) y = [] for i in range(len(loc)): y.append(loc[i][1]) minx = np.min(x) - 3 miny = np.min(y) - 3 maxx = np.max(x) + 3 maxy = np.max(y) + 3 img[markers == -1] = [255, 0, 0] plt.imshow(img) plt.show() roi = img[minx:maxx, miny:maxy] #roi_rgb = cv2.cvtColor(roi, cv2.COLOR_BGR2RGB) plt.imshow(roi) plt.show() cv2.imwrite("roi.jpg", roi)
while True: cv2.imshow('Image',selectOnImage_copy) cv2.imshow('Watershed Segments', segments) k = cv2.waitKey(1) if k == 27: break elif k == ord('c'): selectOnImage_copy = image.copy() marker_image = np.zeros(image.shape[:2],dtype=np.int32) segments = np.zeros(image.shape, dtype=np.uint8) elif k>0 and chr(k).isdigit(): current_marker = int(chr(k)) if marks_updated: marker_image_copy = marker_image.copy() cv2.watershed(image,marker_image_copy) segments = np.zeros(image.shape,dtype=np.uint8) for color_ind in range(n_markers): segments[marker_image_copy==(color_ind)] = colors[color_ind] cv2.imwrite('images/seg.jpg',segments) cv2.destroyAllWindows() cimg = cv2.imread("images/seg.jpg", cv2.IMREAD_GRAYSCALE) circles = cv2.HoughCircles(cimg,cv2.HOUGH_GRADIENT,1.5,120,param1=50,param2=30,minRadius=0,maxRadius=0) circles = np.uint16(np.around(circles)) # print(len(circles[0,:])) img = image.copy() # for circle in circles[0,:]: circle = circles[0,:][0] # draw the outer circle
def heartSeg(file_name): # img_blur = cv2.GaussianBlur(img_origin, (3,3), 0, 0) # img_blur = cv2.blur(img_origin, (5,5)) # Input the image img_origin_name = 'public/data/' + file_name img_origin = cv2.imread(img_origin_name, 1) img_origin_singlechannel = cv2.imread(img_origin_name, 0) # Image smoothing (also reduce noise) img_medianblur = cv2.medianBlur(img_origin_singlechannel, 5) # Apply thresholding to the image twice to get the desired grayscale interval (between 50~145) thresh_val_high = 145 thresh_val_low = 50 ret, thresh = cv2.threshold(img_medianblur, thresh_val_high, 255, cv2.THRESH_TOZERO_INV) ret, img_binary = cv2.threshold(thresh, thresh_val_low, 255, cv2.THRESH_BINARY) # Apply morphology opening to binary image to eliminate small objects kernel = np.ones((3, 3), dtype=np.uint8) img_obj = cv2.morphologyEx(img_binary, cv2.MORPH_OPEN, kernel, iterations=2) # Find the absolute foreground (i.e. objects) by eroding all objects fg = cv2.erode(img_obj, kernel, iterations=3) # Specify heart wall foreground with the condition of object window size fg_labels_num, fg_labels_img, fg_stats, fg_centroids = cv2.connectedComponentsWithStats( fg) muscle_fg_idx = 0 for muscle_fg_idx in range(fg_labels_num): if fg_stats[muscle_fg_idx,cv2.CC_STAT_WIDTH] > 80 and fg_stats[muscle_fg_idx,cv2.CC_STAT_WIDTH] < 120 \ and fg_stats[muscle_fg_idx,cv2.CC_STAT_HEIGHT] > 100 and fg_stats[muscle_fg_idx,cv2.CC_STAT_HEIGHT] < 140: break fg_labels_img[fg_labels_img != muscle_fg_idx] = 0 fg_labels_img[fg_labels_img == muscle_fg_idx] = 1 muscle_fg = fg_labels_img.astype('uint8') muscle_fg = cv2.erode(muscle_fg, kernel, iterations=2) # Specify heart wall region with the condition of object window size bg = img_obj bg_labels_num, bg_labels_img, bg_stats, bg_centroids = cv2.connectedComponentsWithStats( bg) muscle_bg_idx = 0 for muscle_bg_idx in range(bg_labels_num): if bg_stats[muscle_bg_idx,cv2.CC_STAT_WIDTH] > 120 and bg_stats[muscle_bg_idx,cv2.CC_STAT_WIDTH] < 160 \ and bg_stats[muscle_bg_idx,cv2.CC_STAT_HEIGHT] > 120 and bg_stats[muscle_bg_idx,cv2.CC_STAT_HEIGHT] < 160: break bg_labels_img[bg_labels_img != muscle_bg_idx] = 0 bg_labels_img[bg_labels_img == muscle_bg_idx] = 1 muscle_bg = bg_labels_img.astype('uint8') # Find the absolute background by dilating heart wall region muscle_bg = cv2.dilate(muscle_bg, kernel, iterations=7) muscle_fg = muscle_fg.astype('int32') muscle_bg = muscle_bg.astype('int32') # The area between heart wall object and background is unknown area TBD with watershed algorithm muscle_unknown = np.copy(muscle_bg) muscle_unknown[muscle_fg > 0] = 0 ''' markers: >1: absolute foreground (heart wall object) 1: absolute background 0: unknown area (TBD with watershed algorithm) (all 0 will become 1 (bg) or >1 (fg) after watershed algorithm applied) -1: watershed boundaries (generated with watershed algorithm) ''' markers = muscle_fg + 1 markers[muscle_unknown > 0] = 0 # Apply watershed algorithm on Gaussian-blurred image (not the origin one, because the noise is massive) img_gaussblur = cv2.GaussianBlur(img_origin, (3, 3), 0, 0) markers = cv2.watershed(img_gaussblur, markers) # Use our function to generate the image where heart wall region is specified img_out = getWatershedImage(img_origin, markers) if not os.path.isdir('public/result'): os.mkdir('public/result') cv2.imwrite('public/result/result_' + file_name, img_out)
def watershed(self, original): hsv = cv2.cvtColor(original, cv2.COLOR_BGR2HSV) for i in range(len(self.lower_fg)): self.create_window() self.fine_tune_fg(self.lower_fg[i], self.upper_fg[i], hsv, original) for i in range(len(self.lower_bg)): self.create_window_bg() self.fine_tune_bg(self.lower_bg[i], self.upper_bg[i], hsv, original) if self.fg is None or self.bg is None: self.fg = [] self.bg = [] return None, None self.fg = self.fg_array[0] for j in range(len(self.fg_array)): if j > 0: self.fg = cv2.add(self.fg, self.fg_array[j]) self.bg = self.bg_array[0] for j in range(len(self.bg_array)): if j > 0: self.bg = cv2.add(self.bg, self.bg_array[j]) # passa para gray fg_gray = cv2.cvtColor(self.fg, cv2.COLOR_BGR2GRAY) bg_gray = cv2.cvtColor(self.bg, cv2.COLOR_BGR2GRAY) # simplificar Binarias _, thresh_fg = cv2.threshold(fg_gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) _, thresh_bg = cv2.threshold(bg_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # retirar areas comuns que nao interresam mark = cv2.subtract(thresh_bg, thresh_fg) # simplificar markers mark32 = np.int32(cv2.addWeighted(thresh_fg, 1, thresh_bg, 0.5, 0)) markers = mark32 + 1 markers[mark == 255] = 0 # watershed markers = cv2.watershed(original, markers) # encontrar contornos m = cv2.convertScaleAbs(markers) _, m = cv2.threshold(m, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) cntr, h = cv2.findContours(m, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) cv2.drawContours(original, cntr, -1, (255, 255, 255), 2, cv2.LINE_AA) self.create_window_view() while 1: cv2.imshow(self.filename, original) k = cv2.waitKey(5) & 0xFF if k == ord("s"): cv2.destroyAllWindows() self.fg = "" self.bg = "" self.fg_array = [] self.bg_array = [] return original, cntr
def watershed(self): m = self.markers.copy() cv.watershed(self.img, m) overlay = self.colors[np.maximum(m, 0)] vis = cv.addWeighted(self.img, 0.5, overlay, 0.5, 0.0, dtype=cv.CV_8UC3) cv.imshow('watershed', vis)
def main(): #Input the images from the file you want analysed for comparison: img = Original img2 = Labelled cv2.namedWindow("Results") img = cv2.imread(r'originals/001.jpg') img2 = cv2.imread(r'labelled/001.jpg') #Converting the images into grayscale. rows, cols = img.shape[0], img.shape[1] img = cv2.resize(img, (int(cols / 2), int(rows / 2))) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # Noise reduction. kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1) # Identifying the background area of the overall image. sure_bg = cv2.dilate(opening, kernel, iterations=1) # Determining each individual object. (Cells.) sure_fg = cv2.erode(opening, kernel, iterations=1) # Remaining area is the border (seperation area) between the cells and the background. sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg, sure_fg) # Label the interior of each individual cell with a unique label. ret, markers = cv2.connectedComponents(sure_fg) # Add one to all labels so that sure background is not 0, but 1 markers = markers + 1 # Watershed algorithm identifies the boundaries of each cell. markers[unknown == 255] = 0 markers = cv2.watershed(img, markers) # Number of markers is the number of cells in the image. numbers = markers.max() # Calculate the gray-scale variance for each cell and treat all cells that are greater than the maximum value of the (gray-scale variance * var_threshold) as diseased and marked as green. var_threshold = 0.2 mess = [] max_var = 0 for i in range(2, numbers + 1): if gray[markers == i] != []: tmp = gray[markers == i] if tmp.size > 50: pix_var = tmp.var() mess.append((pix_var, i, tmp.min())) if pix_var > max_var: max_var = pix_var disease = [] for i in range(len(mess)): if mess[i][0] >= max_var * var_threshold: disease.append(mess[i][2]) img[markers == mess[i][1]] = [0, 255, 0] #BGR # Traverse all the cells once again to prevent any leaks. # Taking the average of the darkest gray values for each diseased cell as described above, treat all cells that have a darker color than the average* pix_threshold as being diseased and marked in red. pix_threshold = 0.75 for i in range(len(mess)): if mess[i][2] <= np.array(mess).mean() * pix_threshold: img[markers == mess[i][1]] = [0, 0, 255] #BGR # Map all borders in blue for easy viewing. img[markers == -1] = [255, 0, 0] #BGR #Show final results. print('Total Number Of Cells:' + str(numbers)) (r, g, b) = cv2.split(img) img = cv2.merge([b, g, r]) (r, g, b) = cv2.split(img2) img2 = cv2.merge([b, g, r]) plt.figure('Result') plt.subplot(1, 2, 1) plt.imshow(img2) plt.subplot(1, 2, 2) plt.imshow(img) plt.show() # Show grey level histogram. plt.figure('Gray Level Histogram') arr = gray.flatten() n, bins, patches = plt.hist(arr, bins=256, normed=1, facecolor='green', alpha=0.75) plt.show()
print(unknown) # Marker labelling ret, markers = cv.connectedComponents(sure_fg) print(markers.shape) # for x in markers: # print(x) # Add one to all labels so that sure background is not 0, but 1 markers = markers + 1 # Now, mark the region of unknown with zero print(markers[unknown == 255]) markers[unknown == 255] = 0 new_img = np.zeros((312, 252, 3), np.uint8) new_img[:] = (255, 255, 255) cv.imshow('img1', img) print(markers) markers = cv.watershed(img, markers) markers2 = cv.watershed(new_img, markers) # print(markers) img[markers == -1] = [255, 0, 0] new_img[markers == -1] = [255, 0, 0] cv.imshow('img', img) cv.imshow('new_img', new_img) # cv2.waitKey() while (1): # cv2.imshow('newimg', newimg) if cv.waitKey(1) == ord('q'): break
def __init__(self, org_img, org_mask): #画像格納 train_data = org_img[:, :, :3].copy() # omit alpha channel train_data_gray = cv2.cvtColor(train_data, cv2.COLOR_RGB2GRAY) mask_data = org_mask mask_data = mask_data.copy() #ヒストグラム正規化により差が出やすくする clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) equ = clahe.apply(train_data_gray) #equからdatas作成、maskと被ってないとこ消去、ノイズ消去 datas = [] for i in range(0, 256): th = Threshold(equ, i) thd = th.data() kernel = np.ones((5, 5), np.uint8) opening = cv2.morphologyEx(thd, cv2.MORPH_OPEN, kernel) #膨張収縮 closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel) #収縮膨張 inverse = cv2.bitwise_not(closing) #色調反転 data = cv2.bitwise_and(inverse, inverse, mask=mask_data) #maskの輪郭外を消去 datas.append(data) datas.append(mask_data) #最後にmaskを入れる #輪郭配列を作る。 all_contours_array = [] #dataごとのcontoursが全て入っている for data in datas: contours_array = [ ] #contour_array:各画像に対して[フラグ,moment,輪郭]の形で複数入っている image, contours, hierarchy = cv2.findContours( data, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for contour in contours: curve_flag = flag.no_curve #くびれがなければ0 if curve(contour): #くびれがあれば1 curve_flag = flag.curve moment = cv2.moments(contour) #重心 if moment['m00'] != 0: cx = int(moment['m10'] / moment['m00']) cy = int(moment['m01'] / moment['m00']) else: cx = 0 cy = 0 contours_array.append([curve_flag, [cx, cy], contour]) all_contours_array.append(contours_array) seeds = [] #watershedアルゴリズムの前景となる輪郭を入れる配列 first_outer_contours = [] #datas256番=mask_dataで輪郭を取得。くびれていなければseedsへ。くびれていたらfirst_outer_contoursへ。 first_contours_array = all_contours_array[256] for contour_array in first_contours_array: if contour_array[0] == flag.curve: first_outer_contours.append(contour_array[2]) elif contour_array[0] == flag.no_curve: seeds.append(contour_array[2]) #255番からループスタート Search(255, first_outer_contours, all_contours_array, seeds) img = np.copy(train_data) contour_img = cv2.drawContours(img, seeds, -1, (125, 125, 0), 1) zero = np.zeros(mask_data.shape) devided = cv2.fillPoly(zero, pts=seeds, color=(255, 255, 255)) #分割されたやつ devided = np.uint8(devided) #前景となる場所を決める dist_transform = cv2.distanceTransform(devided, cv2.DIST_L2, 5) ret, sure_fg = cv2.threshold(dist_transform, 0.1 * dist_transform.max(), 255, 0) #背景となる場所を決める kernel = np.ones((3, 3), np.uint8) sure_bg = cv2.dilate(mask_data, kernel, iterations=3) sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg, sure_fg) ret, markers = cv2.connectedComponents(sure_fg) markers = markers + 1 # 不明領域に0をつけておく markers[unknown == 255] = 0 #watershedアルゴリズムを行う markers = cv2.watershed(train_data, markers) self.__data = markers
img = cv2.imread('C:/Users/Ferhat/Desktop/img3.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU) # noise removal kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2) # sure background area sure_bg = cv2.dilate(opening, kernel, iterations=5) # Finding sure foreground area dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) ret, sure_fg = cv2.threshold(dist_transform, 0.2 * dist_transform.max(), 255, 50) # Finding unknown region sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg, sure_fg) # Marker labelling ret, markers = cv2.connectedComponents(sure_fg) # Add one to all labels so that sure background is not 0, but 1 markers = markers + 1 # Now, mark the region of unknown with zero markers[unknown == 255] = 0 markers = cv2.watershed(img, markers) img[markers == -1] = [255, 0, 0] cv2.imwrite('C:/Users/Ferhat/Desktop/img1213.jpg', img)
## find compromise for overlapping areas if len(polygon) > 0: # label non-cell areas background_label = i + 2 labels[labels == 0] = background_label # label overlapping areas labels[cell_count > 1] = 0 # apply watershed algorithm to fill in overlap areas. The "image" entry is an array of zeros, so that the # boundaries extend uniformly without paying attention to the original histology image (otherwise, the # boundaries will be crooked) labels = watershed(np.zeros(im.size[::-1] + (3,), dtype=np.uint8), np.array(labels)) # set background pixels back to zero labels[labels == background_label] = 0 # compute borders between labels, because in some cases, adjacent cells have intermittent overlaps # that produce interrupted 0 boundaries borders = mahotas.labeled.borders(labels, mode='ignore') # add borders to the labels labels[borders] = 0 if DEBUG: plt.subplot(224) plt.imshow(labels)
def processing(data): print(data) file_num = int(len(data)) # Reading 3 images to work img = [cv2.imread(i, cv2.IMREAD_UNCHANGED) for i in data[:file_num]] try: print('Original size', img[0].shape) myshape = img[0].shape except AttributeError: print("shape not found") # -------------------------------- # setting dim of the resize height = myshape[0] width = myshape[1] dim = (width, height) res_img = [] for i in range(len(img)): res = cv2.resize(img[i], dim, interpolation=cv2.INTER_LINEAR) res_img.append(res) # Checcking the size try: print('RESIZED', res_img[1].shape) except AttributeError: print("shape not found") # Visualizing one of the images in the array #original = res_img[1] #display_one(original) # ---------------------------------- # Remove noise # Using Gaussian Blur no_noise = [] for i in range(len(res_img)): #blur = cv2.GaussianBlur(res_img[i], (5, 5), 0) blur = cv2.bilateralFilter(res_img[i], 5, 100, 100) no_noise.append(blur) for i in range(len(res_img)): original = res_img[i] image = no_noise[i] #display(original, image, 'Original', 'Blured') im = Image.fromarray(image) myname = data[i] mynamestring = str(myname[+image_path_length:]) print("no_noise_path", no_noise_path) print("my_name", mynamestring) #im.save(f"{no_noise_path}{mynamestring}") #--------------------------------- # Segmentation gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) im5 = Image.fromarray(gray) ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) ret, thresh1 = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV) ret, thresh2 = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU) ret, thresh3 = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU) th4 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 11, 4) #increasing to 4 keeps features but removes noise #display(thresh, thresh2, "Their thresh", "My Thresh") im2 = Image.fromarray(thresh) # Further noise removal (Morphology) kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2) im6 = Image.fromarray(th4) # sure background area sure_bg = cv2.dilate(opening, kernel, iterations=3) # Displaying sure background #display(original, sure_bg, 'Original', 'Sure background') # Finding sure foreground area dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0) # Finding unknown region sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg, sure_fg) #Displaying unknown #display(original, unknown, 'Original', 'Unknown') #Displaying segmented back ground #display(original, sure_bg, 'Original', 'Segmented Background') im3 = Image.fromarray(sure_bg) # Marker labelling ret, markers = cv2.connectedComponents(sure_fg) # Add one to all labels so that sure background is not 0, but 1 markers = markers + 1 # Now, mark the region of unknown with zero markers[unknown == 255] = 0 markers = cv2.watershed(image, markers) image[markers == -1] = [0, 0, 255] im4 = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) im4 = Image.fromarray(im4) im.save(f"{no_noise_path}{mynamestring}") im2.save(f"{segmented_path}{mynamestring}") im3.save(f"{segmented_background_path}{mynamestring}") im4.save(f"{markers_path}{mynamestring}") im5.save(f"{grey_path}{mynamestring}") im6.save(f"{adapthresh_path}{mynamestring}")
def get_mask_watershed(image, thresh, aprox_seg, debug=False): """Returns the mask of an accurate segmentation based on a approximate segmentation and an aggresive threshold. Arguments: image {cv2 image} -- The image where the search will be perfomed thresh {np 2d binary array} -- An aggresive threshold mask of the organ aprox_seg {np 2d binary array} -- An aproximate segmentation of the organ Keyword Arguments: debug {bool} -- Set True to see the full contours given by watershed (default: {False}) Returns: np 2d binary array -- An accurate mask of the organ """ width, height = image.shape # Part of mask we're "sure" is the organ sure_fg = np.zeros((width, height, 1), np.uint8) # Part of mask we're "sure" isn't the organ sure_bg = np.zeros((width, height, 1), np.uint8) for i in range(width): for j in range(height): coord = i, j sure_bg[coord] = 255 # If it is part of an aggresive threshold, # and part of an approximate contour, it should be the organ if aprox_seg[coord] and thresh[i][j]: sure_fg[coord] = 255 # If it isn't part of either, it should be ignored elif not aprox_seg[coord] and not thresh[i][j]: sure_bg[coord] = 0 # Parts we'll have to find what they are unknown = cv2.subtract(sure_bg, sure_fg) # Get the markers for watershed _, markers = cv2.connectedComponents(sure_fg) # Add one to all labels so that sure background is not 0, but 1 markers = markers + 1 # Now, mark the region of unknown with zero markers[unknown == 255] = 0 # Wathershed only works with rgb images backtorgb = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB) # Watershed returnes markers of a background, and different foregrounds markers = cv2.watershed(backtorgb, markers) # In our case: # 1 - Background # 2 - The organ we're interested in # 3... - Other organs or bones if debug: marked = backtorgb marked[markers == -1] = [0, 255, 0] cv2.imshow('markers', marked) cv2.waitKey() # Since we started the search fron the organ, the first # foreground region will be the organ of interest mask = np.zeros((width, height), np.uint8) for i in range(markers.shape[0]): for j in range(markers.shape[1]): if markers[i, j] == 2: mask[i, j] = 1 return mask
def test(args): data_loader = CTW1500TestLoader(long_size=args.long_size) test_loader = torch.utils.data.DataLoader(data_loader, batch_size=1, shuffle=False, num_workers=2, drop_last=True) submit_path = 'outputs_shape' if os.path.exists(submit_path): shutil.rmtree(submit_path) os.mkdir(submit_path) # Setup Model if args.arch == "resnet50": model = models.resnet50(pretrained=True, num_classes=7, scale=args.scale) elif args.arch == "resnet101": model = models.resnet101(pretrained=True, num_classes=7, scale=args.scale) elif args.arch == "resnet152": model = models.resnet152(pretrained=True, num_classes=7, scale=args.scale) for param in model.parameters(): param.requires_grad = False model = model.cuda() if args.resume is not None: if os.path.isfile(args.resume): print("Loading model and optimizer from checkpoint '{}'".format( args.resume)) checkpoint = torch.load(args.resume) # model.load_state_dict(checkpoint['state_dict']) d = collections.OrderedDict() for key, value in checkpoint['state_dict'].items(): tmp = key[7:] d[tmp] = value model.load_state_dict(d) print("Loaded checkpoint '{}' (epoch {})".format( args.resume, checkpoint['epoch'])) sys.stdout.flush() else: print("No checkpoint found at '{}'".format(args.resume)) sys.stdout.flush() model.eval() total_frame = 0.0 total_time = 0.0 for idx, (org_img, img) in enumerate(test_loader): print('progress: %d / %d' % (idx, len(test_loader))) sys.stdout.flush() img = Variable(img.cuda(), volatile=True) org_img = org_img.numpy().astype('uint8')[0] text_box = org_img.copy() torch.cuda.synchronize() start = time.time() outputs = model(img) score = torch.sigmoid(outputs[:, 0, :, :]) outputs = (torch.sign(outputs - args.binary_th) + 1) / 2 text = outputs[:, 0, :, :] kernels = outputs[:, 0:args.kernel_num, :, :] * text score = score.data.cpu().numpy()[0].astype(np.float32) text = text.data.cpu().numpy()[0].astype(np.uint8) kernels = kernels.data.cpu().numpy()[0].astype(np.uint8) # # c++ version pse # # pred = pse(kernels, args.min_kernel_area / (args.scale * args.scale)) # # python version pse # pred = pypse(kernels, args.min_kernel_area / (args.scale * args.scale)) # # scale = (org_img.shape[0] * 1.0 / pred.shape[0], org_img.shape[1] * 1.0 / pred.shape[1]) # scale = (org_img.shape[1] * 1.0 / pred.shape[1], org_img.shape[0] * 1.0 / pred.shape[0]) # label = pred # label_num = np.max(label) + 1 # bboxes = [] tmp_marker = kernels[-1, :, :] # for i in range(args.kernel_num-2, -1, -1): # sure_fg = tmp_marker # sure_bg = kernels[i, :, :] # watershed_source = cv2.cvtColor(sure_bg, cv2.COLOR_GRAY2BGR) # unknown = cv2.subtract(sure_bg,sure_fg) # ret, marker = cv2.connectedComponents(sure_fg) # label_num = np.max(marker) # marker += 1 # marker[unknown==1] = 0 # marker = cv2.watershed(watershed_source, marker) # marker[marker==-1] = 1 # marker -= 1 # tmp_marker = np.asarray(marker, np.uint8) sure_fg = kernels[-1, :, :] sure_bg = text watershed_source = cv2.cvtColor(sure_bg, cv2.COLOR_GRAY2BGR) unknown = cv2.subtract(sure_bg, sure_fg) ret, marker = cv2.connectedComponents(sure_fg) label_num = np.max(marker) marker += 1 marker[unknown == 1] = 0 marker = cv2.watershed(watershed_source, marker) marker -= 1 label = marker # label = tmp_marker # scale = (w / marker.shape[1], h / marker.shape[0]) scale = (org_img.shape[1] * 1.0 / marker.shape[1], org_img.shape[0] * 1.0 / marker.shape[0]) bboxes = [] for i in range(1, label_num): points = np.array(np.where(label == i)).transpose((1, 0))[:, ::-1] if points.shape[0] < args.min_area / (args.scale * args.scale): continue score_i = np.mean(score[label == i]) if score_i < args.min_score: continue # rect = cv2.minAreaRect(points)1 binary = np.zeros(label.shape, dtype='uint8') binary[label == i] = 1 # a=cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # print(a) contours, _ = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) contour = contours[0] # epsilon = 0.01 * cv2.arcLength(contour, True) # bbox = cv2.approxPolyDP(contour, epsilon, True) bbox = contour if bbox.shape[0] <= 2: continue bbox = bbox * scale bbox = bbox.astype('int32') bboxes.append(bbox.reshape(-1)) torch.cuda.synchronize() end = time.time() total_frame += 1 total_time += (end - start) print('fps: %.2f' % (total_frame / total_time)) sys.stdout.flush() for bbox in bboxes: cv2.drawContours(text_box, [bbox.reshape(bbox.shape[0] // 2, 2)], -1, (0, 255, 0), 2) image_name = data_loader.img_paths[idx].split('/')[-1].split('.')[0] write_result_as_txt(image_name, bboxes, 'outputs_shape/submit_ctw1500/') text_box = cv2.resize(text_box, (text.shape[1], text.shape[0])) debug(idx, data_loader.img_paths, [[text_box]], 'outputs_shape/vis_ctw1500/')