positioning algorithm

2019-05-23  本文已影响0人  求索_700e

定位算法

import cv2

import os

import numpy as np

BATTERY_WIDTH=1700

BATTERY_HEIGHT=750

BATTERY_SIZE_CHANGE_RATIO=0.2

AREA_EXPAND_RATIO=1.1

PIECES_WIDTH_NUM=6

PIECES_HEIGHT_NUM=2

PIECES_LENGTH=320

CENTER_REGION_OFFSET={'left':150,'right':180,'top':100,'bottom':100}

class Split_():

  def __init__(self):

        "input:"

        self.img_red=0

        self.img_blue=0

        self.img_green=0

        "output:"

        #self.affined_image_merged=0

        #self.centerRegion_gridX=[]

        #self.centerRegion_gridY=[]

        self.center_pieces=[]

        "debug:"

        self.image_name=""

  def obtain_contous(self):

        ret, thresh_map = cv2.threshold(self.img_red, 127,255, cv2.THRESH_BINARY)     

        image, contours, hier = cv2.findContours(thresh_map, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

        return contours

  def area_expand(self, p1, p2, iS_bottom_top_mode):##面积扩充函数

                  cx=(p1[0]+p2[0])/2

                  cy=(p1[1]+p2[1])/2

                  p1[0]=cx-abs(cx-p1[0])*AREA_EXPAND_RATIO

                  p2[0]=cx+abs(cx-p2[0])*AREA_EXPAND_RATIO

                  if iS_bottom_top_mode==True:

                      p1[1]=cy+abs(cy-p1[1])*AREA_EXPAND_RATIO

                      p2[1]=cy-abs(cy-p2[1])*ARA_EXPAND_RATIO

                  else:             

                      p1[1]=cy-abs(cy-p1[1])*AREA_EXPAND_RATIO

                      p2[1]=cy+abs(cy-p2[1])*AREA_EXPAND_RATIO

                  return p1,p2

  def find_four_corners(self,contours):##找出四个角点的坐标

      for c in contours:

          # find bounding box coordinates

          x,y,w,h = cv2.boundingRect(c)##x,y is the left_top point

          battery_size=BATTERY_HEIGHT*BATTERY_WIDTH 

          #print(w,h)   

          if w*h<battery_size*(1+BATTERY_SIZE_CHANGE_RATIO) and w*h>battery_size*(1-BATTERY_SIZE_CHANGE_RATIO):

              # find minimum area

            rect = cv2.minAreaRect(c)

            # calculate coordinates of the minimum area rectangle

            box = cv2.boxPoints(rect)## return four points [(x,y)

            box = np.int0(box)

            left_bottom,right_top=self.area_expand(box[0],box[2],True)##box[0]=left_bottom,box[1]=left_top,box[2]=right_top

            left_top,right_bottom=self.area_expand(box[1],box[3],False)

            self.corner_points={"left_bottom": left_bottom,##定位出来的,在原图像中,电池的四个角点。

                                "left_top":left_top,

                                "right_top":right_top,

                                "right_bottom":right_bottom

                                }

            # draw contours

            #cv2.drawContours(self.img_c, [box], 0, (0,0, 255), 3)

            break

      '''

      cv2.namedWidow("contours",cv2.WINDOW_NORMAL)

      cv2.imshow("contours", self.img_c)

      cv2.imwrite("./_gird.jpg",self.img_c)

      cv2.waitKey()

      cv2.destroyAllWindows()

      '''

  def inverse_affine_transform(self):

          src_points =np.float32( [self.corner_points['left_top'], self.corner_points['right_top'], self.corner_points['left_bottom'],

                            self.corner_points['right_bottom']])##要被摳出來的原圖像中的四個角點。

          # 变换后分别在左上、右上、左下、右下四个点

          dst_points = np.float32([(0,0), (BATTERY_WIDTH, 0),

                              (0, BATTERY_HEIGHT), (BATTERY_WIDTH, BATTERY_HEIGHT)])#摳出來後,映射到的四個角點位置,也就是圖像的大小。

          # 生成透视变换矩阵

          M = cv2.getPerspectiveTransform(src_points, dst_points)

          # 进行透视变换

          affined_red = cv2.warpPrspective(self.img_red, M, (BATTERY_WIDTH, BATTERY_HEIGHT),borderValue=(255,255,255)) 

          affined_green = cv2.warpPerspective(self.img_green, M, (BATTERY_WIDTH, BATTERY_HEIGHT),borderValue=(255,255,255)) 

          affined_blue = cv2.warpPerspective(self.img_blue, M, (BATTERY_WIDTH, BATTERY_HEIGHT),borderValue=(255,255,255)) 

          self.affined_image_merged=cv2.merge([affined_red,affined_green,affined_blue])

  def adjust_center_region(self):

          #self.center_adjusted_image_merged=self.affined_image_merged[CENTER_REGION_OFFSET['top']:BATTERY_HEIGHT-CENTER_REGION_OFFSET['bottom'], \

          #                                                    CENTER_REGION_OFFSET['left']:BATTERY_WIDTH-CENTER_REGION_OFFSET['right'],:]

          self.center_adjusted_width=BATTERY_WIDTH-CENTER_REGION_OFFSET['left']-CENTER_REGION_OFFSET['right']

          self.center_adjusted_height=BATTERY_HEIGHT-CENTER_REGION_OFFSET['top']-CENTER_REGION_OFFSET['bottom']

  def cal_overlap_ratio(self):

        def check(is_width,overlap_ratio):

            if overlap_ratio<0.05 or overlap_ratio>0.5:

                if is_width:

                    raise ValueError("width overlao_ratio=%s is not reasonable"%overlap_ratio)

                else:

                    raise ValueError("height overlao_ratio=%s is not reasonable"%overlap_ratio)\

            return overlap_ratio

        self.centerRegion_overlap_ratio_width=check(True, (PIECES_WIDTH_NUM*PIECES_LENGTH-self.center_adjusted_width)/((PIECES_WIDTH_NUM-1)*PIECES_LENGTH) )

        self.centerRegion_overlap_ratio_height=check(False, (PIECES_HEIGHT_NUM*PIECES_LENGTH-self.center_adjusted_height)/((PIECES_HEIGHT_NUM- \

                                                      1)*PIECES_LENGTH) )

  def construct_centerRegion_grid(self):

      self.centerRegion_gridX=[]

      self.centerRegion_gridY=[]

      for n in range(PIECES_WIDTH_NUM):

            self.centerRegion_gridX.append([CENTER_REGION_OFFSET['left']+int(n*PIECES_LENGTH*(1-self.centerRegion_overlap_ratio_width)), \

                  CENTER_REGION_OFFSET['left']+int(n*PIECES_LENGTH*(1-self.centerRegion_overlap_ratio_width)+PIECES_LENGTH)])## [start,end] positions

      for n in range(PIECES_HEIGHT_NUM):

            self.centerRegion_gridY.append([CENTER_REGION_OFFSET['top']+int(n*PIECES_LENGTH*(1-self.centerRegion_overlap_ratio_height)), \

                  CENTER_REGION_OFFSET['top']+int(n*PIECES_LENGTH*(1-self.centerRegion_overlap_ratio_height)+PIECES_LENGTH)])## [start,end] positions

      '''

      for x in range(0, PIECES_WIDTH_NUM):

          for y in range(0, PIECES_HEIGHT_NUM):

                point_start= (self.centerRegion_gridX[x][0],self.centerRegion_gridY[y][0])

                point_end=  (self.centerRegion_gridX[x][1],self.centerRegion_gridY[y][1])

                cv2.circle(self.affined_image_merged, point_start, 1,  (0, 0, 255) , 5)

                cv2.circle(self.affined_image_merged, point_end, 1,  (0, 255, 0) , 5)

      cv2.imwrite("./"+self.image_name, self.affined_image_merged)

      '''

  def cut_into_small_pieces(self):

      self.center_pieces=[]

      for y in range(0, PIECES_HEIGHT_NUM):

          for x in range(0, PIECES_WIDTH_NUM):

                xmin=self.centerRegion_gridX[x][0]

                ymin=self.centerRegion_gridY[y][0]

                xmax=self.centerRegion_gridX[x][1]

                ymax=self.centerRegion_gridY[y][1]

                cut_img=self.affined_image_merged[ymin:ymax,xmin:xmax,:]

                #cv2.imwrite("./output/"+self.image_name.split()[0]+"_"+str(idx)+".jpg", cut_img)

                #idx+=1

                self.center_pieces.append({"xmin":xmin,"ymin":ymin,"xmax":xmax,"ymax":ymax,"image":cut_img})

  def get_test_data(self, Split, img_red, img_green, img_blue):

      Split.img_red=img_red

      Split.img_green=img_green

      Split.img_blue=img_blue

      contours=Split.obtain_contours()

      Split.find_four_corners(contours)

      Split.inverse_affine_transform()

      Split.adjust_center_region()

      Split.cal_overlap_ratio()         

      Split.construct_centerRegion_grid()

      Split.cut_into_small_pieces()

      return self.affined_image_merged, self.center_pieces

if __name__ == '__main__':

    img = cv2.imread("/home/ta/1.bmp", cv2.IMREAD_UNCHANGED)

    fname=os.listdir("/home/ta/Desktop/gs_for_test/blue/")

    Split=Split()

    for f in fname:

      Split.img_red=cv2.imread("/home/1/"+f, cv2.IMREAD_UNCHANGED)

      Split.img_green=cv2.imread("/home/2/"+f, cv2.IMREAD_UNCHANGED)

      Split.img_blue=cv2.imread("/home/3/"+f, cv2.IMREAD_UNCHANGED)

      Split.image_name=f

      contours=Split.obtain_contours()  ##二值化,获得轮廓信息,对轮廓进行最小外接矩形包围框提取,

      Split.find_four_corners(contours)## 根据包围框信息,以及约束条件,查找目标,排除干扰。

      Split.inverse_affine_transform()##逆透视投影变换,矫正并分离出目标。

      Split.adjust_center_region()

      Split.cal_overlap_ratio()         

      Split.construct_centerRegion_grid()

      Split.cut_into_small_pieces()

      print(f)

上一篇下一篇

猜你喜欢

热点阅读