日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

opencv-python画局部放大图

發布時間:2024/3/24 python 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 opencv-python画局部放大图 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 為什么要畫局部放大圖?
  • 程序邏輯
  • 程序實例

這項功能的目的是為了方便使用opencv做圖像標注工具。

為什么要畫局部放大圖?

在做圖像數據標注時,很難一次就做到精準標注,經常需要微調才能達到比較好的標注效果。如果目標比較小,即使微調也難以做到精準,所以就需要另外一個窗口對標注區域進行局部放大以方便微調。

程序邏輯

本文中標注信息以矩形框作為示例,矩形框是圖像標注中最常用到的一種標注信息形態。其他標注信息的設計邏輯雷同。

程序主要邏輯是:鼠標在任意窗口中做的操作都要同步映射到另外一個窗口。主要通過兩個維度進行控制:1. 鼠標在主窗口還是在放大窗口;2. 鼠標的操作。其中主窗口指的是用來顯示完整大圖的窗口,放大窗口是用來顯示局部放大區域的窗口。

  • 鼠標在主窗口
    • 鼠標移動:以當前點(current_pt)為中心顯示一塊放大區域,顯示的范圍由一個參數指定default_zoom_image_size。為了確保以current_pt為中心向四個方向均能取到default_zoom_image_size一半的值,current_pt的活動范圍是大圖減去一定的邊緣區域,這個邊緣區域就是default_zoom_image_size的一半。在活動范圍內,current_pt等同于鼠標當前點,在邊緣區域,current_pt等于距離鼠標當前點最近的邊緣點。
    • 鼠標畫矩形框:左鍵按下并拖動可以畫矩形框,矩形框不會超出大圖邊界
    • 刪除矩形框:有兩種情況會刪除矩形框 —— 1. 左鍵畫出來的矩形框面積為零;2. 右鍵點擊
  • 鼠標在放大窗口
    • 鼠標移動:什么也不做。
    • 鼠標畫矩形框:左鍵按下并拖動可以畫矩形框,矩形框可以超出放大窗口的邊界,但是不會超出大圖邊界
    • 刪除矩形框:同主窗口的兩種情況
    • 鼠標左鍵或右鍵點擊:可以起到選擇current_pt的作用

總體來說,我們在主窗口做任何操作都可以比較隨意,因為主窗口中除了矩形框外,圖像本身不發生變化。而在放大窗口中做操作就需要相對保守一些,不然會非常亂,以至于無法操作。所以我們在主窗口中畫矩形框時,放大窗口會隨著矩形框不停改變;而我們在放大窗口中畫矩形框時,放大窗口則保持不變(不然眼花繚亂)。

程序實例

把程序邏輯搞明白后下面代碼就比較容易懂了。細節就不多說了,只說一個需要注意的大方向:我們需要為兩個窗口各寫一個鼠標回調函數。
先看一下單純畫矩形框的代碼可能會有助于理解下面程序中的一些細節:opencv-python鼠標畫矩形框:cv2.rectangle()

# -*- coding: utf-8 -*- import cv2class Rect(object):def __init__(self, pt1=(0, 0), pt2=(0, 0)):self.tl = pt1self.br = pt2self.regularize()def regularize(self):"""make sure tl = TopLeft point, br = BottomRight point"""tl = (min(self.tl[0], self.br[0]), min(self.tl[1], self.br[1]))br = (max(self.tl[0], self.br[0]), max(self.tl[1], self.br[1]))self.tl = tlself.br = brdef get_center(self):"""get center point of Rect"""center_x = (self.tl[0] + self.br[0]) // 2center_y = (self.tl[1] + self.br[1]) // 2return center_x, center_ydef get_width(self):"""get width of Rect"""return abs(self.br[0] - self.tl[0])def get_height(self):"""get height of Rect"""return abs(self.br[1] - self.tl[1])def height_over_width(self):"""ratio of height over width"""return self.get_height() / self.get_width()def get_area(self):"""get area of Rect"""return self.get_width() * self.get_height()class DrawZoom(object):def __init__(self, image, color,current_pt=(0, 0),default_zoom_image_size=(256, 256)):self.original_image = imageself.color = colorself.thickness = 2self.current_pt = current_ptself.default_zoom_image_size = default_zoom_image_sizeself.rect_in_big_image = Rect()self.rect_in_zoom_image = Rect()self.zoom_offset = (0, 0)self.is_drawing_big = Falseself.is_drawing_zoom = Falseself.exist_rect = Falseself.big_image = image.copy()self.zoom_image = Noneself.zoom_image_backup = Noneself.get_zoom_image()def get_image_height(self):"""get height of big image"""return self.original_image.shape[0]def get_image_width(self):"""get width of big image"""return self.original_image.shape[1]def get_margin_height(self):"""get height of margin. in the margin area of big image, coordinate ofcurrent_pt does NOT change"""return self.default_zoom_image_size[0] // 2def get_margin_width(self):"""get width of margin"""return self.default_zoom_image_size[1] // 2def get_zoom_image(self, height_ratio_expand=0.2, width_ratio_expand=0.2):"""get zoom image for two cases: the rect exists or not.height_ratio_expand and width_ratio_expand are used for expanding somearea of rect"""if not self.exist_rect:self.get_zoom_image_for_current_pt()elif self.rect_in_big_image.get_area() > 0:self.get_zoom_image_for_rect(height_ratio_expand,width_ratio_expand)def get_zoom_image_for_current_pt(self):"""get zoom image for current mouse point (when rect does not exist)"""# (x, y) is center coordinatex = max(self.current_pt[0], self.get_margin_width())x = min(x, self.get_image_width() - self.get_margin_width())y = max(self.current_pt[1], self.get_margin_height())y = min(y, self.get_image_height() - self.get_margin_height())tl_x = x - self.get_margin_width()tl_y = y - self.get_margin_height()br_x = x + self.get_margin_width()br_y = y + self.get_margin_height()tl_x, tl_y, br_x, br_y = self.shrink_rect(tl_x, tl_y, br_x, br_y)self.zoom_image = self.big_image[tl_y:br_y, tl_x:br_x]self.zoom_image_backup = self.original_image[tl_y:br_y, tl_x:br_x]self.zoom_offset = (tl_x, tl_y)def get_zoom_image_for_rect(self, height_ratio_expand, width_ratio_expand):"""get zoom image when rect exists"""if self.rect_in_big_image.get_area() == 0:return Noneheight_over_width_for_win_zoom = \self.default_zoom_image_size[1] / self.default_zoom_image_size[0]center = self.rect_in_big_image.get_center()if self.rect_in_big_image.height_over_width() > \height_over_width_for_win_zoom:half_height = int(0.5 * (1 + height_ratio_expand) *self.rect_in_big_image.get_height())half_width = int(half_height / height_over_width_for_win_zoom)else:half_width = int(0.5 * (1 + width_ratio_expand) *self.rect_in_big_image.get_width())half_height = int(half_width * height_over_width_for_win_zoom)tl_x = center[0] - half_widthtl_y = center[1] - half_heightbr_x = center[0] + half_widthbr_y = center[1] + half_heighttl_x, tl_y, br_x, br_y = self.shrink_rect(tl_x, tl_y, br_x, br_y)self.zoom_image = self.big_image[tl_y:br_y, tl_x:br_x]self.zoom_image_backup = self.original_image[tl_y:br_y, tl_x:br_x]self.zoom_offset = (tl_x, tl_y)@staticmethoddef clip(value, low, high):"""clip value between low and high"""output = max(value, low)output = min(output, high)return outputdef shrink_point(self, x, y):"""shrink point (x, y) to inside big image"""x_shrink = self.clip(x, 0, self.get_image_width())y_shrink = self.clip(y, 0, self.get_image_height())return x_shrink, y_shrinkdef shrink_rect(self, pt1_x, pt1_y, pt2_x, pt2_y):"""shrink rect to inside big image"""pt1_x = self.clip(pt1_x, 0, self.get_image_width())pt1_y = self.clip(pt1_y, 0, self.get_image_height())pt2_x = self.clip(pt2_x, 0, self.get_image_width())pt2_y = self.clip(pt2_y, 0, self.get_image_height())rect = Rect((pt1_x, pt1_y), (pt2_x, pt2_y))rect.regularize()tl_x, tl_y = rect.tlbr_x, br_y = rect.brreturn tl_x, tl_y, br_x, br_ydef reset_big_image(self):"""reset big_image (for show) using original image"""self.big_image = self.original_image.copy()def reset_zoom_image(self):"""reset zoom_image (for show) using the zoom image backup"""self.zoom_image = self.zoom_image_backup.copy()def draw_rect_in_big_image(self):"""draw rect in big image"""cv2.rectangle(self.big_image,self.rect_in_big_image.tl, self.rect_in_big_image.br,color=self.color, thickness=self.thickness)def draw_rect_in_zoom_image(self):"""draw rect in zoom image"""cv2.rectangle(self.zoom_image,self.rect_in_zoom_image.tl, self.rect_in_zoom_image.br,color=self.color, thickness=self.thickness)def update_drawing_big(self):"""update drawing big image, and map the corresponding area to zoom image"""if self.exist_rect:self.draw_rect_in_big_image()self.get_zoom_image()def update_drawing_zoom(self):"""update drawing big and zoom image when drawing rect in zoom image"""if self.exist_rect:self.draw_rect_in_big_image()self.draw_rect_in_zoom_image()def onmouse_big_image(event, x, y, flags, draw_zoom):if event == cv2.EVENT_LBUTTONDOWN:# pick first point of rectdraw_zoom.is_drawing_big = Truedraw_zoom.rect_in_big_image.tl = (x, y)draw_zoom.exist_rect = Trueelif draw_zoom.is_drawing_big and event == cv2.EVENT_MOUSEMOVE:# pick second point of rect and draw current rectdraw_zoom.rect_in_big_image.br = draw_zoom.shrink_point(x, y)draw_zoom.reset_big_image()draw_zoom.update_drawing_big()elif event == cv2.EVENT_LBUTTONUP:# finish drawing current rectdraw_zoom.is_drawing_big = Falsedraw_zoom.rect_in_big_image.br = draw_zoom.shrink_point(x, y)draw_zoom.rect_in_big_image.regularize()if draw_zoom.rect_in_big_image.get_area() == 0:draw_zoom.reset_big_image()draw_zoom.rect_in_big_image = Rect()draw_zoom.exist_rect = Falsedraw_zoom.update_drawing_big()elif (not draw_zoom.is_drawing_big) and event == cv2.EVENT_RBUTTONDOWN:# right button down to erase current rectdraw_zoom.rect_in_big_image = Rect()draw_zoom.exist_rect = Falsedraw_zoom.reset_big_image()draw_zoom.update_drawing_big()else:# default case: mouse move without rectdraw_zoom.current_pt = (x, y)draw_zoom.update_drawing_big()def onmouse_zoom_image(event, x, y, flags, draw_zoom):if event == cv2.EVENT_LBUTTONDOWN:# pick first point of rectdraw_zoom.is_drawing_zoom = Truedraw_zoom.rect_in_zoom_image.tl = (x, y)draw_zoom.rect_in_big_image.tl = (x + draw_zoom.zoom_offset[0],y + draw_zoom.zoom_offset[1])draw_zoom.exist_rect = Trueelif draw_zoom.is_drawing_zoom and event == cv2.EVENT_MOUSEMOVE:# pick second point of rect and draw current rectdraw_zoom.rect_in_zoom_image.br = (x, y)draw_zoom.rect_in_big_image.br = draw_zoom.shrink_point(x + draw_zoom.zoom_offset[0], y + draw_zoom.zoom_offset[1])draw_zoom.reset_zoom_image()draw_zoom.reset_big_image()draw_zoom.update_drawing_zoom()elif event == cv2.EVENT_LBUTTONUP:# finish drawing current rectdraw_zoom.is_drawing_zoom = Falsedraw_zoom.rect_in_big_image.br = draw_zoom.shrink_point(x + draw_zoom.zoom_offset[0], y + draw_zoom.zoom_offset[1])draw_zoom.rect_in_big_image.regularize()if draw_zoom.rect_in_big_image.get_area() == 0:draw_zoom.reset_big_image()draw_zoom.rect_in_big_image = Rect()draw_zoom.rect_in_zoom_image = Rect()draw_zoom.exist_rect = Falsedraw_zoom.current_pt = draw_zoom.shrink_point(x + draw_zoom.zoom_offset[0], y + draw_zoom.zoom_offset[1])draw_zoom.update_drawing_big()elif (not draw_zoom.is_drawing_big) and event == cv2.EVENT_RBUTTONDOWN:# right button down to erase current rectdraw_zoom.rect_in_big_image = Rect()draw_zoom.rect_in_zoom_image = Rect()draw_zoom.exist_rect = Falsedraw_zoom.reset_big_image()draw_zoom.current_pt = draw_zoom.shrink_point(x + draw_zoom.zoom_offset[0], y + draw_zoom.zoom_offset[1])draw_zoom.update_drawing_big()else:# mousemove in zoom image will not change the content of imagepassif __name__ == '__main__':WIN_NAME_BIG = 'big_image'WIN_NAME_ZOOM = 'zoom_image'image = cv2.imread('1.jpg')draw_zoom = DrawZoom(image, (0, 255, 0))cv2.namedWindow(WIN_NAME_BIG, 0)cv2.namedWindow(WIN_NAME_ZOOM, 0)cv2.setMouseCallback(WIN_NAME_BIG, onmouse_big_image, draw_zoom)cv2.setMouseCallback(WIN_NAME_ZOOM, onmouse_zoom_image, draw_zoom)while True:cv2.imshow(WIN_NAME_BIG, draw_zoom.big_image)cv2.imshow(WIN_NAME_ZOOM, draw_zoom.zoom_image)key = cv2.waitKey(30)if key == 27: # ESCbreakcv2.destroyAllWindows()

結果:

總結

以上是生活随笔為你收集整理的opencv-python画局部放大图的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。