positioning algorithm
定位算法
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)