版本一

import copy
import cv2
import numpy as npWIN_NAME = 'draw_rect'class Rect(object):def __init__(self):self.tl = (0, 0)self.br = (0, 0)def regularize(self):"""make sure tl = TopLeft point, br = BottomRight point"""pt1 = (min(self.tl[0], self.br[0]), min(self.tl[1], self.br[1]))pt2 = (max(self.tl[0], self.br[0]), max(self.tl[1], self.br[1]))self.tl = pt1self.br = pt2class DrawRects(object):def __init__(self, image, color, thickness=1, center=(10,10), radius=100):self.original_image = imageself.image_for_show = image.copy()self.color = colorself.thickness = thicknessself.rects = []self.current_rect = Rect()self.left_button_down = Falseself.center = centerself.radius = radiusself.clearImg = np.zeros((image.shape[0], image.shape[1], 4), dtype=np.uint8)self.image_for_show_line = image.copy()@staticmethoddef __clip(value, low, high):"""clip value between low and highParameters----------value: a numbervalue to be clippedlow: a numberlow limithigh: a numberhigh limitReturns-------output: a numberclipped value"""output = max(value, low)output = min(output, high)return outputdef shrink_point(self, x, y):"""shrink point (x, y) to inside image_for_showParameters----------x, y: int, intcoordinate of a pointReturns-------x_shrink, y_shrink: int, intshrinked coordinate"""height, width = self.image_for_show.shape[0:2]x_shrink = self.__clip(x, 0, width)y_shrink = self.__clip(y, 0, height)return (x_shrink, y_shrink)def append(self):"""add a rect to rects list"""self.rects.append(copy.deepcopy(self.current_rect))def pop(self):"""pop a rect from rects list"""rect = Rect()if self.rects:rect = self.rects.pop()return rectdef reset_image(self):"""reset image_for_show using original image"""self.image_for_show = self.original_image.copy()def draw(self):"""draw rects on image_for_show"""for rect in self.rects:cv2.rectangle(self.image_for_show, rect.tl, rect.br,color=self.color, thickness=self.thickness)def draw_current_rect(self):"""draw current rect on image_for_show"""cv2.rectangle(self.image_for_show,self.current_rect.tl, self.current_rect.br,color=self.color, thickness=self.thickness)# 保存结果def save_images_rect(self):cv2.imwrite("Rect.jpg", draw_rects.image_for_show)def draw_crossline(self):pt_left = (self.center[0] - self.radius, self.center[1])pt_right = (self.center[0] + self.radius, self.center[1])pt_top = (self.center[0], self.center[1] - self.radius)pt_bottom = (self.center[0], self.center[1] + self.radius)cv2.line(self.image_for_show, pt_left, pt_right,(0, 0, 255), 1)cv2.line(self.image_for_show, pt_top, pt_bottom,(0, 0, 255), 1)def onmouse_draw_rect(event, x, y, flags, draw_rects):draw_rects.center = (x, y)if event == cv2.EVENT_LBUTTONDOWN:# pick first point of rectprint('pt1: x = %d, y = %d' % (x, y))draw_rects.left_button_down = Truedraw_rects.current_rect.tl = (x, y)if draw_rects.left_button_down and event == cv2.EVENT_MOUSEMOVE:# pick second point of rect and draw current rectdraw_rects.current_rect.br = draw_rects.shrink_point(x, y)draw_rects.reset_image()draw_rects.draw()draw_rects.draw_current_rect()draw_rects.save_images_rect()if event == cv2.EVENT_LBUTTONUP:# finish drawing current rect and append it to rects listdraw_rects.left_button_down = Falsedraw_rects.current_rect.br = draw_rects.shrink_point(x, y)print('pt2: x = %d, y = %d' % (draw_rects.current_rect.br[0],draw_rects.current_rect.br[1]))draw_rects.current_rect.regularize()draw_rects.append()if (not draw_rects.left_button_down) and event == cv2.EVENT_RBUTTONDOWN:# pop the last rect in rects listdraw_rects.pop()draw_rects.reset_image()draw_rects.draw()draw_rects.save_images_rect()# print("clear")if __name__ == '__main__':image = cv2.imread("result.png")draw_rects = DrawRects(image, (0, 255, 0), 2, (10, 10), 10000)cv2.namedWindow(WIN_NAME, 0)cv2.setMouseCallback(WIN_NAME, onmouse_draw_rect, draw_rects)while True:cv2.imshow(WIN_NAME, draw_rects.image_for_show)key = cv2.waitKey(30)if key == 27:  # ESCbreakcv2.destroyAllWindows()

在版本一的基础上加十字瞄准线

通过两图叠加,不太满意,会影响原图的本来显示情况

import copy
import cv2
import numpy as npWIN_NAME = 'draw_rect'class Rect(object):def __init__(self):self.tl = (0, 0)self.br = (0, 0)def regularize(self):"""make sure tl = TopLeft point, br = BottomRight point"""pt1 = (min(self.tl[0], self.br[0]), min(self.tl[1], self.br[1]))pt2 = (max(self.tl[0], self.br[0]), max(self.tl[1], self.br[1]))self.tl = pt1self.br = pt2class DrawRects(object):def __init__(self, image, color, thickness=1, center=(10,10), radius=100):self.original_image = imageself.image_for_show = image.copy()self.color = colorself.thickness = thicknessself.rects = []self.current_rect = Rect()self.left_button_down = Falseself.center = centerself.radius = radiusself.image_for_show_line = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)@staticmethoddef __clip(value, low, high):"""clip value between low and highParameters----------value: a numbervalue to be clippedlow: a numberlow limithigh: a numberhigh limitReturns-------output: a numberclipped value"""output = max(value, low)output = min(output, high)return outputdef shrink_point(self, x, y):"""shrink point (x, y) to inside image_for_showParameters----------x, y: int, intcoordinate of a pointReturns-------x_shrink, y_shrink: int, intshrinked coordinate"""height, width = self.image_for_show.shape[0:2]x_shrink = self.__clip(x, 0, width)y_shrink = self.__clip(y, 0, height)return (x_shrink, y_shrink)def append(self):"""add a rect to rects list"""self.rects.append(copy.deepcopy(self.current_rect))def pop(self):"""pop a rect from rects list"""rect = Rect()if self.rects:rect = self.rects.pop()return rectdef reset_image(self):"""reset image_for_show using original image"""self.image_for_show = self.original_image.copy()def draw(self):"""draw rects on image_for_show"""for rect in self.rects:cv2.rectangle(self.image_for_show, rect.tl, rect.br,color=self.color, thickness=self.thickness)def draw_current_rect(self):"""draw current rect on image_for_show"""cv2.rectangle(self.image_for_show,self.current_rect.tl, self.current_rect.br,color=self.color, thickness=self.thickness)# 保存结果def save_images_rect(self):cv2.imwrite("Rect.jpg", draw_rects.image_for_show)def trans_img(self):self.image_for_show_line = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)def draw_crossline(self):self.trans_img()pt_left = (self.center[0] - self.radius, self.center[1])pt_right = (self.center[0] + self.radius, self.center[1])pt_top = (self.center[0], self.center[1] - self.radius)pt_bottom = (self.center[0], self.center[1] + self.radius)cv2.line(self.image_for_show_line, pt_left, pt_right,(0, 0, 255), 3)cv2.line(self.image_for_show_line, pt_top, pt_bottom,(0, 0, 255), 3)# cv2.imshow("crossLine", self.image_for_show_line)# print("crossline")def onmouse_draw_rect(event, x, y, flags, draw_rects):draw_rects.center = (x, y)if event == cv2.EVENT_LBUTTONDOWN:# pick first point of rectprint('pt1: x = %d, y = %d' % (x, y))draw_rects.left_button_down = Truedraw_rects.current_rect.tl = (x, y)if draw_rects.left_button_down and event == cv2.EVENT_MOUSEMOVE:# pick second point of rect and draw current rectdraw_rects.current_rect.br = draw_rects.shrink_point(x, y)draw_rects.reset_image()draw_rects.draw()draw_rects.draw_current_rect()draw_rects.save_images_rect()if event == cv2.EVENT_LBUTTONUP:# finish drawing current rect and append it to rects listdraw_rects.left_button_down = Falsedraw_rects.current_rect.br = draw_rects.shrink_point(x, y)print('pt2: x = %d, y = %d' % (draw_rects.current_rect.br[0],draw_rects.current_rect.br[1]))draw_rects.current_rect.regularize()draw_rects.append()if (not draw_rects.left_button_down) and event == cv2.EVENT_RBUTTONDOWN:# pop the last rect in rects listdraw_rects.pop()draw_rects.reset_image()draw_rects.draw()draw_rects.save_images_rect()# print("clear")draw_rects.draw_crossline()if __name__ == '__main__':image = cv2.imread("result.png")draw_rects = DrawRects(image, (0, 255, 0), 2, (10, 10), 10000)cv2.namedWindow(WIN_NAME, 0)cv2.setMouseCallback(WIN_NAME, onmouse_draw_rect, draw_rects)while True:# cv2.imshow(WIN_NAME, draw_rects.image_for_show)# cv2.imshow(WIN_NAME, two_images_merge(draw_rects.image_for_show,draw_rects.image_for_show_line))# cv2.imshow("img1", draw_rects.image_for_show)# cv2.imshow("img2", draw_rects.image_for_show_line)# cv2.waitKey()dest = cv2.addWeighted(draw_rects.image_for_show_line,0.1, draw_rects.image_for_show,0.9, 20)cv2.imshow(WIN_NAME, dest)key = cv2.waitKey(30)if key == 27:  # ESCbreakcv2.destroyAllWindows()

版本三,完善实现功能

dest = cv2.addWeighted(draw_rects.image_for_show_line,0.1, draw_rects.image_for_show,0.9, 20)
修改为
dest = cv2.add(draw_rects.image_for_show_line, draw_rects.image_for_show)
import copy
import cv2
import numpy as npWIN_NAME = 'draw_rect'class Rect(object):def __init__(self):self.tl = (0, 0)self.br = (0, 0)def regularize(self):"""make sure tl = TopLeft point, br = BottomRight point"""pt1 = (min(self.tl[0], self.br[0]), min(self.tl[1], self.br[1]))pt2 = (max(self.tl[0], self.br[0]), max(self.tl[1], self.br[1]))self.tl = pt1self.br = pt2class DrawRects(object):def __init__(self, image, color, thickness=1, center=(10,10), radius=100):self.original_image = imageself.image_for_show = image.copy()self.color = colorself.thickness = thicknessself.rects = []self.current_rect = Rect()self.left_button_down = Falseself.center = centerself.radius = radiusself.image_for_show_line = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)@staticmethoddef __clip(value, low, high):"""clip value between low and highParameters----------value: a numbervalue to be clippedlow: a numberlow limithigh: a numberhigh limitReturns-------output: a numberclipped value"""output = max(value, low)output = min(output, high)return outputdef shrink_point(self, x, y):"""shrink point (x, y) to inside image_for_showParameters----------x, y: int, intcoordinate of a pointReturns-------x_shrink, y_shrink: int, intshrinked coordinate"""height, width = self.image_for_show.shape[0:2]x_shrink = self.__clip(x, 0, width)y_shrink = self.__clip(y, 0, height)return (x_shrink, y_shrink)def append(self):"""add a rect to rects list"""self.rects.append(copy.deepcopy(self.current_rect))def pop(self):"""pop a rect from rects list"""rect = Rect()if self.rects:rect = self.rects.pop()return rectdef reset_image(self):"""reset image_for_show using original image"""self.image_for_show = self.original_image.copy()def draw(self):"""draw rects on image_for_show"""for rect in self.rects:cv2.rectangle(self.image_for_show, rect.tl, rect.br,color=self.color, thickness=self.thickness)def draw_current_rect(self):"""draw current rect on image_for_show"""cv2.rectangle(self.image_for_show,self.current_rect.tl, self.current_rect.br,color=self.color, thickness=self.thickness)# 保存结果def save_images_rect(self):cv2.imwrite("Rect.jpg", draw_rects.image_for_show)def trans_img(self):self.image_for_show_line = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)def draw_crossline(self):self.trans_img()pt_left = (self.center[0] - self.radius, self.center[1])pt_right = (self.center[0] + self.radius, self.center[1])pt_top = (self.center[0], self.center[1] - self.radius)pt_bottom = (self.center[0], self.center[1] + self.radius)cv2.line(self.image_for_show_line, pt_left, pt_right,(0, 0, 255), 1)cv2.line(self.image_for_show_line, pt_top, pt_bottom,(0, 0, 255), 1)# cv2.imshow("crossLine", self.image_for_show_line)# print("crossline")def onmouse_draw_rect(event, x, y, flags, draw_rects):draw_rects.center = (x, y)if event == cv2.EVENT_LBUTTONDOWN:# pick first point of rectprint('pt1: x = %d, y = %d' % (x, y))draw_rects.left_button_down = Truedraw_rects.current_rect.tl = (x, y)if draw_rects.left_button_down and event == cv2.EVENT_MOUSEMOVE:# pick second point of rect and draw current rectdraw_rects.current_rect.br = draw_rects.shrink_point(x, y)draw_rects.reset_image()draw_rects.draw()draw_rects.draw_current_rect()draw_rects.save_images_rect()if event == cv2.EVENT_LBUTTONUP:# finish drawing current rect and append it to rects listdraw_rects.left_button_down = Falsedraw_rects.current_rect.br = draw_rects.shrink_point(x, y)print('pt2: x = %d, y = %d' % (draw_rects.current_rect.br[0],draw_rects.current_rect.br[1]))draw_rects.current_rect.regularize()draw_rects.append()if (not draw_rects.left_button_down) and event == cv2.EVENT_RBUTTONDOWN:# pop the last rect in rects listdraw_rects.pop()draw_rects.reset_image()draw_rects.draw()draw_rects.save_images_rect()# print("clear")draw_rects.draw_crossline()if __name__ == '__main__':image = cv2.imread("result.png")draw_rects = DrawRects(image, (0, 255, 0), 2, (10, 10), 10000)cv2.namedWindow(WIN_NAME, 0)cv2.setMouseCallback(WIN_NAME, onmouse_draw_rect, draw_rects)while True:dest = cv2.add(draw_rects.image_for_show_line, draw_rects.image_for_show)cv2.imshow(WIN_NAME, dest)key = cv2.waitKey(30)if key == 27:  # ESCbreakcv2.destroyAllWindows()

版本4 保存画框的ROI

import copy
import cv2
import numpy as npWIN_NAME = 'draw_rect'class Rect(object):def __init__(self):self.tl = (0, 0)self.br = (0, 0)def regularize(self):"""make sure tl = TopLeft point, br = BottomRight point"""pt1 = (min(self.tl[0], self.br[0]), min(self.tl[1], self.br[1]))pt2 = (max(self.tl[0], self.br[0]), max(self.tl[1], self.br[1]))self.tl = pt1self.br = pt2class DrawRects(object):def __init__(self, image, color, thickness=1, center=(10, 10), radius=100):self.original_image = imageself.image_for_show = image.copy()self.color = colorself.thickness = thicknessself.rects = []self.current_rect = Rect()self.left_button_down = Falseself.center = centerself.radius = radiusself.image_for_show_line = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)@staticmethoddef __clip(value, low, high):"""clip value between low and highParameters----------value: a numbervalue to be clippedlow: a numberlow limithigh: a numberhigh limitReturns-------output: a numberclipped value"""output = max(value, low)output = min(output, high)return outputdef getROI(self):roi = image[self.current_rect.tl[1]:self.current_rect.br[1], self.current_rect.tl[0]:self.current_rect.br[0]]cv2.imwrite("ROI.jpg",roi)def shrink_point(self, x, y):"""shrink point (x, y) to inside image_for_showParameters----------x, y: int, intcoordinate of a pointReturns-------x_shrink, y_shrink: int, intshrinked coordinate"""height, width = self.image_for_show.shape[0:2]x_shrink = self.__clip(x, 0, width)y_shrink = self.__clip(y, 0, height)return (x_shrink, y_shrink)def append(self):"""add a rect to rects list"""self.rects.append(copy.deepcopy(self.current_rect))def pop(self):"""pop a rect from rects list"""rect = Rect()if self.rects:rect = self.rects.pop()return rectdef reset_image(self):"""reset image_for_show using original image"""self.image_for_show = self.original_image.copy()def draw(self):"""draw rects on image_for_show"""for rect in self.rects:cv2.rectangle(self.image_for_show, rect.tl, rect.br,color=self.color, thickness=self.thickness)def draw_current_rect(self):"""draw current rect on image_for_show"""cv2.rectangle(self.image_for_show,self.current_rect.tl, self.current_rect.br,color=self.color, thickness=self.thickness)# 保存结果def save_images_rect(self):cv2.imwrite("Rect.jpg", draw_rects.image_for_show)def trans_img(self):self.image_for_show_line = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)def draw_crossline(self):self.trans_img()pt_left = (self.center[0] - self.radius, self.center[1])pt_right = (self.center[0] + self.radius, self.center[1])pt_top = (self.center[0], self.center[1] - self.radius)pt_bottom = (self.center[0], self.center[1] + self.radius)cv2.line(self.image_for_show_line, pt_left, pt_right,(0, 0, 255), 1)cv2.line(self.image_for_show_line, pt_top, pt_bottom,(0, 0, 255), 1)# cv2.imshow("crossLine", self.image_for_show_line)# print("crossline")def onmouse_draw_rect(event, x, y, flags, draw_rects):draw_rects.center = (x, y)if event == cv2.EVENT_LBUTTONDOWN:# pick first point of rectprint('pt1: x = %d, y = %d' % (x, y))draw_rects.left_button_down = Truedraw_rects.current_rect.tl = (x, y)if draw_rects.left_button_down and event == cv2.EVENT_MOUSEMOVE:# pick second point of rect and draw current rectdraw_rects.current_rect.br = draw_rects.shrink_point(x, y)draw_rects.reset_image()draw_rects.draw()draw_rects.draw_current_rect()draw_rects.save_images_rect()if event == cv2.EVENT_LBUTTONUP:# finish drawing current rect and append it to rects listdraw_rects.left_button_down = Falsedraw_rects.current_rect.br = draw_rects.shrink_point(x, y)print('pt2: x = %d, y = %d' % (draw_rects.current_rect.br[0],draw_rects.current_rect.br[1]))draw_rects.current_rect.regularize()draw_rects.append()draw_rects.getROI()if (not draw_rects.left_button_down) and event == cv2.EVENT_RBUTTONDOWN:# pop the last rect in rects listdraw_rects.pop()draw_rects.reset_image()draw_rects.draw()draw_rects.save_images_rect()# print("clear")draw_rects.draw_crossline()if __name__ == '__main__':image = cv2.imread("result.jpg")draw_rects = DrawRects(image, (0, 255, 0), 2, (10, 10), 10000)cv2.namedWindow(WIN_NAME, 0)cv2.setMouseCallback(WIN_NAME, onmouse_draw_rect, draw_rects)while True:dest = cv2.add(draw_rects.image_for_show_line, draw_rects.image_for_show)cv2.imshow(WIN_NAME, dest)key = cv2.waitKey(30)if key == 27:  # ESCbreakcv2.destroyAllWindows()

opencv十字瞄准线 在图像上长按左键画矩形单击右键清除相关推荐

  1. cesium 鼠标操作习惯修改 鼠标左键旋转 鼠标右键平移

    修改鼠标操作习惯 // 倾斜视图 鼠标左键旋转 viewer.scene.screenSpaceCameraController.tiltEventTypes = [ Cesium.CameraEve ...

  2. MFC消息处理时,双击鼠标左键响应单击左键消息的处理

    今天做老师留下来的作业题,莫名其妙出现Bug,然后发现是MFC消息处理机制的问题,在响应鼠标双击前,会先产生一个单击鼠标消息,这里是我的解决方法. 单击响应: void CMouseView::OnL ...

  3. mouseup 左键_javascript中mouseup事件丢失的原因与解决办法

    这篇文章主要跟大家介绍了关于Javascript中mouseup事件丢失的原因与解决办法的相关资料,文中给出详细的示例代码供大家参考学习,需要的朋友们下面跟着小编一起来学习学习吧. 前言 当实现类似E ...

  4. 计算机鼠标左键不起作用,鼠标左键失灵怎么办 鼠标左键失灵处理方法【详解】...

    现在使用电脑的特别多,我们使用电脑时使用最频繁的就是鼠标和键盘了,我们输入都是需要它们的,但是使用时间长了之后,难免会出现鼠标点击能听到咔哒的声音,但是就没反应,或者是一单机就变成双击,或者点击半天什 ...

  5. wps右键失效_鼠标左键失灵右键代替左键怎么设置

    鼠标左键失灵右键代替左键怎么设置 导读:小编根据大家的需要整理了一份关于<鼠标左键失灵右键代替左键怎么设置>的内容,具体内容:有时候鼠标左键失灵了,又没有备用了,怎么办?这时我们可以通过设 ...

  6. Ubuntu 10.10 无线鼠标左键失灵问题

    今天台机装了Ubuntu10.10 在千辛万苦搞定Raid0的问题后,又出现鼠标左键失灵 系统刚开始的时候比较正常,貌似几分钟后鼠标左键失灵,右键正常,键盘正常. 同时插入USB有线鼠标和无线键鼠,鼠 ...

  7. php控制鼠标,HTML_用VBS控制鼠标的实现代码(获取鼠标坐标、鼠标移动、鼠标单击、鼠标双击、鼠标右击),怎么用VBS模拟鼠标左键单击、 - phpStudy...

    用VBS控制鼠标的实现代码(获取鼠标坐标.鼠标移动.鼠标单击.鼠标双击.鼠标右击) 怎么用VBS模拟鼠标左键单击.左键双击.右键单击?-- 网上搜到的答案普遍是VBS无法实现,或者是要用第三方COM( ...

  8. 使用Python和OpenCV对轮廓进行排序(从左到右,自上而下)

    使用Python和OpenCV对轮廓进行排序(从左到右,自上而下) 1. 效果图 2. 原理 3. 源码 参考 使用轮廓来构建移动文档扫描仪. 使用轮廓来检测图像中的条形码. 利用轮廓来找到从相机到物 ...

  9. 使用 OpenCV 和 Tesseract 对图像中的感兴趣区域 (ROI) 进行 OCR

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 在这篇文章中,我们将使用 OpenCV 在图像的选定区域上应用 O ...

  10. OpenCV之core 模块. 核心功能(1)Mat - 基本图像容器 OpenCV如何扫描图像、利用查找表和计时 矩阵的掩码操作 使用OpenCV对两幅图像求和(求混合(blending))

    Mat - 基本图像容器 目的 从真实世界中获取数字图像有很多方法,比如数码相机.扫描仪.CT或者磁共振成像.无论哪种方法,我们(人类)看到的是图像,而让数字设备来"看"的时候,则 ...

最新文章

  1. 《Advanced PHP Programming》读书笔记
  2. GitHub超3k星!从Python代码到APP只需要一个小工具~
  3. About darwin OS
  4. 模型压缩高达75%,推理速度提升超20%,百度Paddle Lite v2.3正式发布
  5. boost之timer,progress_timer,progress_display的介绍及使用
  6. SIP与RTP综合应用5-RTP解包过程
  7. OSChina 周六乱弹 ——世上无难事,只要肯放弃!
  8. ASP.NET MVC应用程序把文字写在图片上
  9. 数学建模day1 层次分析法与TOPSIS方法
  10. deepin有线网卡无法连接网络
  11. 100%可用的总裁主题授权版 WordPress付费资源素材下载主题
  12. QQ群文件下载速度慢-解决办法
  13. win10+yolov5尝鲜体验
  14. 点击行的数据回填到模态框
  15. Java开源Web框架
  16. 时间都去哪儿了——2014年总结
  17. AppleTV的设置
  18. 修复无限网卡驱动报错:windows仍在设置此设备的类配置(代码56)
  19. Delphi获取汉字拼音以及拼音首字母
  20. android网上订餐项目相关配置

热门文章

  1. HDU 1224 DFS
  2. 你可能不知道的21个PS技巧
  3. Java JRE 6安全更新
  4. Windows10关闭自动更新的多种方式
  5. SpringMVC整合activiti Modeler
  6. 计算机中的数学【集合论】现代数学的共同基础
  7. Python最详细的 机器学习算法:逻辑回归的推导及实战 你值得拥有!
  8. linux系统属于操作系统吗,linux属于什么操作系统
  9. 速读原著-TCP/IP(IP首部)
  10. Linux perlbrew Perl5 安装教程