最重要的写在前面:

文末:我曾尝试用OpenCV中算子来还原Halcon中的算子,但是受时间和经验的限制,只能进行到如下:如果后续有必须应用OpenCV的场景,再结合起来搞。

但是最重要的经验是:

1、Halcon提供了一整套解决问题的方案,而不像OpenCV那样从头造轮子。OpenCV除非经验和使用很熟,否则很难找到思路。而Halcon提供了大量的案例。

2、在Halcon中,提供了大量的方案,基于方案提供的思路用OpenCV复现的意义不大了。

3、如果非要用OpenCV,那么在Halcon中有F1帮助文档:可以查询算子的用法。除了对算法的用法解释外,还有【Possible Predecessors】和【Possible Successors】,这两者也提示了我们这个算子的前后应用操作。而且,通过算子最下面的【HDevelop例程】可以更好的找到实际的应用场景,以此来找到解决我们的问题的方案。

所以:专心学Halcon吧。

当你做一件事的时候,你就专心做一件事,把它学精。然后才有拓展的资本。发散、迁移、联想必须建立在一定专注力和理解力上,学不深,发散也不准确。画虎不像反类犬。

千万不要让OpenCV的思想,影响Halcon的学习。底层的思维可以相同,但不能依靠。灵活应变。

HALCON中的算子大全(中英对照)


视觉由四门学科构成:

  1. 图像处理:
  2. 数学:
  3. 光学:《工程光学》
  4. 软件(语言)工具、软件架构

数学:矩阵变换、导数。

光学:几何光学(光路,相差、)、物理光学(衍射、干涉)。


图像有十大学科分支:

  1. 图像基本理论
  2. 图像灰度变换
  3. 图像增强
  4. 图像几何变换
  5. 形态学
  6. 图像分割
  7. 图像复原
  8. 图像频域
  9. 运动图像
  10. 图像配准

图像处理的进阶:模式识别、行为识别:真正接近人工智能的东西。:(人脸识别、车牌识别、指纹识别、虹膜识别)


安防视觉、无人机视觉、工业视觉。


二维客户需求:

  1. 识别定位
  2. 符号识别
  3. 测量需求
  4. 缺陷检测(六大方法)(难度最大)
  5. 手眼标定和抓取:(人手和脑的关系。)手脑运动三种通信方式:串口、网口、运动板卡。

识别定位:

基于条件:打光条件的稳定。否则视觉检测效果不好。

  1. blob分析+仿射变换(几何变换):blob分析:连通域分析。
    Blob分析就是对前景、背景分离(阈值筛选二值化)后的 二值图像,进行连通域提取标记。标记完成的每一个Blob都代表一个前景目标(halcon默认标红,颜色可以换),然后就可以计算连通区域Blob的一些相关特征,如:面积、质心、外接矩形等几何特征,还可以计算Blob的颜色、纹理特征,这些特征都可以作为跟踪的依据。ROI提取。
  2. 模板匹配+仿射变换

相机的采集方式:

  • 同步采集:
  • 异步采集:

图像处理的常规套路:

第一步:采集图像

第二步:预处理:灰色对比度拉开。便于提取Blob。几何变换(旋转)

去噪声,中值滤波、高斯滤波(距离加权)、均值滤波。孤立点去除。

抠图,ROI提取。去掉边缘干扰。

第三步:图像分割:二值化、形态学、特征选择

第四步:识别显示、通信


形态学变换:膨胀腐蚀:

膨胀:轮廓变大

腐蚀:轮廓变小

开运算Opening:侵蚀然后膨胀。先侵蚀掉前景目标外围周边的小噪声,然后再膨胀恢复。完成前景之外的去噪。

闭运算Closing:膨胀然后侵蚀。关闭前景对象内的小孔或对象上的小黑点。区域内去噪。保证区域内的纯度。

一个是去掉前景目标中外围周边的噪点。一个是去掉目标前景内部的噪点。


第一步:图像采集:

打开Halcon中菜单栏【助手】中第一个【打开新的Image Acquisition】,在【资源】栏中【图像获取接口】中点击【自动检测接口】,然后搜索到你需要的设备。点击【连接】栏中,选择颜色空间:BGR还是Gray,代表了采集灰色还是彩色。

点击【连接】【实时】从【图形窗口】中检查是否看到了图像。

【参数】中,有相机采集参数设置:

grab_timeout:抓取延时。

shutter:快门,曝光时间。

contrast:对比度

hue:色调:是整个图像的色彩倾向:可见光光谱中能量最强时的波长。

saturation:饱和度:越高色彩越鲜艳。可见光的相对带宽。

brightness:可见光的能量强度。

sharpness:锐化,清晰度。

gamma:灰度值。参数微调。

点击【代码生成】中【插入代码】在【程序窗口】中看到生成的代码。在【采集】中:有个【控制流】和【采集模式】:控制流:有在循环中采集、仅初始化、采集单幅图像。采集模式:同步和异步。

以下是异步:先开始采集,然后同时Do something。

* Image Acquisition 01: Code generated by Image Acquisition 01
* Image Acquisition 01: Attention: The initialization may fail in case parameters need to
* Image Acquisition 01: be set in a specific order (e.g., image resolution vs. offset).
open_framegrabber ('DirectShow', 1, 1, 0, 0, 0, 0, 'default', 8, 'rgb', -1, 'false', 'default', '[0] Integrated Camera', 0, -1, AcqHandle)
set_framegrabber_param (AcqHandle, 'grab_timeout', 5000)
set_framegrabber_param (AcqHandle, 'sharpness', 2)
grab_image_start (AcqHandle, -1)
while (true)grab_image_async (Image, AcqHandle, -1)* Image Acquisition 01: Do something
endwhile
close_framegrabber (AcqHandle)

认识算子函数:按【F1】即可打开Halcon的【HDevelop帮助窗口】

认识第一个算子函数:open_framegrabber:Open and configure an image acquisition device.打开图像采集终端。

set_framegrabber_param:设置终端参数

grab_image获取图像。

下面是同步采集代码:采集和Do something一起干。

close_framegrabber (AcqHandle):关闭终端。

下面是同步所产生的代码:

* Image Acquisition 01: Code generated by Image Acquisition 01
* Image Acquisition 01: be set in a specific order (e.g., image resolution vs. offset).
open_framegrabber ('DirectShow', 1, 1, 0, 0, 0, 0, 'default', 8, 'rgb', -1, 'false', 'default', '[0] Integrated Camera', 0, -1, AcqHandle)
set_framegrabber_param (AcqHandle, 'grab_timeout', 5000)
set_framegrabber_param (AcqHandle, 'sharpness', 2)
* Image Acquisition 01: Attention: The initialization may fail in case parameters need to
while (true)grab_image (Image, AcqHandle)* Image Acquisition 01: Do something
endwhile
close_framegrabber (AcqHandle)

【F5】是连续运行,【F6】是单步运行。工具栏中也可操作。当执行到程序最下方后。可以通过【F2】重置程序执行或【shift + F2】重置程序执行。将程序窗口中的执行光标移动到最初位置。


通过【Ctrl + E】可以打开halcon的【实例程序】,通过实例程序中的的招数算子拆分出来,学习,应用到自己的场景中。

我们打开第一个案例:【方法】【Blob分析】中【ball.hdev】(Inspect ball bondings)   焊点定位检测。

* ball.hdev: Inspection of Ball Bonding
* 1、采集图像
dev_update_window ('off')
dev_close_window ()
dev_open_window (0, 0, 728, 512, 'black', WindowID)
read_image (Bond, 'die/die_03')
dev_display (Bond)
set_display_font (WindowID, 14, 'mono', 'true', 'false')
disp_continue_message (WindowID, 'black', 'true')
stop ()
* 2、预处理+区域抠图
threshold (Bond, Bright, 100, 255)
shape_trans (Bright, Die, 'rectangle2')
dev_set_color ('green')
dev_set_line_width (3)
dev_set_draw ('margin')
dev_display (Die)
disp_continue_message (WindowID, 'black', 'true')
stop ()
reduce_domain (Bond, Die, DieGrey)
* 3、图像分割
threshold (DieGrey, Wires, 0, 50)
fill_up_shape (Wires, WiresFilled, 'area', 1, 100)
dev_display (Bond)
dev_set_draw ('fill')
dev_set_color ('red')
dev_display (WiresFilled)
disp_continue_message (WindowID, 'black', 'true')
stop ()
opening_circle (WiresFilled, Balls, 15.5)
dev_set_color ('green')
dev_display (Balls)
disp_continue_message (WindowID, 'black', 'true')
stop ()
connection (Balls, SingleBalls)
dev_set_color ('blue')
dev_display (SingleBalls)
disp_continue_message (WindowID, 'black', 'true')
stop ()
select_shape (SingleBalls, IntermediateBalls, 'circularity', 'and', 0.85, 1.0)
sort_region (IntermediateBalls, FinalBalls, 'first_point', 'true', 'column')
dev_display (Bond)
dev_set_colored (12)
dev_display (FinalBalls)
disp_continue_message (WindowID, 'black', 'true')
stop ()
* 4、计算显示
smallest_circle (FinalBalls, Row, Column, Radius)
NumBalls := |Radius|
Diameter := 2 * Radius
meanDiameter := mean(Diameter)
minDiameter := min(Diameter)
dev_display (Bond)
disp_circle (WindowID, Row, Column, Radius)
dev_set_color ('white')
disp_message (WindowID, 'D: ' + Diameter$'.4', 'image', Row - 2 * Radius, Column, 'white', 'false')
dev_update_window ('on')

1、采集图像:

程序启动或者关闭期间。自动切换图像对象窗口。关闭原窗口,打开新的窗口,句柄。读取图像,并显示。图像所在位置为:C:\Users\Public\Documents\MVTec\HALCON-17.12-Progress\examples\images\die下:即用户\公用\文档\MVTec中。

2、区域分割:

第12行:threshold:二值化(输入图像、输出变量、最小阈值、最大阈值);在变量窗口可以看到Bright变量,点击即可查看每个变量的图像。

第13行:shape_trans:返回带方框的矩形。凸性检测(图形上任意两个点之间相连,如果线上的点没有在区域内,则将线内所有区域填充。)。返回区域凸性匹配形状。匹配的形状由第三个参数拟合。第三个参数可以为:convex:凸多边形,凸包;ellipse:椭圆形;outer_circle:最小外接圆;inner_circle:最大范围圆;rectangle1:平行于坐标系的最小外接矩形;rectangle2:最小外接矩形;inner_rectangle1:最大轴平行区域矩形;inner_center:中心骨架。形状转换的是为了抠图。粗略的确定要操作的区域。返回值Die相当于一个mask。

第20行:reduce_domain:Reduce the domain of an image。相当于原图与Die做了mask与运算。以此来实现切割。

3、图像分割:

第22行:threshold:进一步二值化滤波范围在(0, 50)之间;在【工具栏】中找到【打开灰度直方图】在【范围筛选及代码生成中】点击小图标【使用该输出】,然后在直方图中拖动左右的两个定标尺,即可通过阈值来选择出我们需要的区域。

注意:两个标尺,分别移动,查看效果。

该案例中,左标尺,从左移动到右端无法选出我们的roi,但是向左滑动右标尺即把上限降低,可以筛选出我们的ROI。因为图中焊点区域为黑色,所以应该设上限。

拖动右标尺,直到我们的黑色区域被选中。

在该工具界面中【输入和输出】中,通过设置颜色,可以标定我们所选中的区域。比如我们这是blue,那么蓝色区域即为我们当前阈值筛选下来的区域。

点击【插入代码】即可生成我们过程程序。

注意一个小技巧:在【可视化】菜单栏中,选择【更新窗口】在【单步模式】选择【清空并显示】将显示你当前变量的图像。

第23行:fill_up_shape:Fill up holes in regions having given shape features.类似分水岭法。通过多次腐蚀,提取sure_fg,通过开运算,求临近区域,做差提取周边区域。

有噪声点:首先想到腐蚀开运算。

第31行:opening_circle:Open a region with a circular structuring element。开运算。类似与watershed之前的连通域之后的的markers。观察变量空间的图像可知。剩余七个圆点和右下角一个方框。然后对这个八个点用圆去查找。

开运算结构元素形状问题:用圆去做开运算,那么结束以后,它越接近于圆。没有棱角。如果用矩形,之后就会有棱角。半径越大,腐蚀越厉害。半径越小,擦除越少。

开运算之后。

第36行:connection: Compute connected components of a region。计算连通域。我在36行之后多加了一个显示:如下:只是为了看看connect返回值:SingleBalls。四邻域,八邻域。

将整个region分割8个区域。由一个region变量变成8个region区域变量。(砍开)

返回的变量singleBalls在图像上右键点击:【显示目录】发现8个变量。

dev_set_color ('blue')
dev_display (SingleBalls)
disp_continue_message (WindowID, 'black', 'true')
stop ()

第41行select_shape: Choose regions with the aid of shape features.:借助形状特征选择regions。第三个参数可选各种形状指标:circularity:圆度。形状匹配功能。类似与opencv中的cv2.matchShapes()。只不过opencv自己去找特征轮廓遍历设阈值。halcon通过选择形状参数来拟合。更定制性。形状自动匹配好还是,指定好,这个看场景来决定,没有绝对之说。

形状选择完之后就只剩下七个焊点图。

调用【打开特征直方图】横坐标表示特征的值,纵坐标表示值的个数。从图上可以看到有一个单独孤立的直线。那就是右下方的方块。还可以通过【特征选择及代码生成】中的【加号+】来增加特征和通道。以此增加特征来区分众多区域。最终实现对于特定区域的筛选定位。在当前特征area中通过与【灰度直方图】中一样,拖动左右定标尺实现对于目标的选择。最大最小面积筛选目标区域。

在案例代码中:采用的特征是圆度circularity。圆度这个特征更明显好用些。上面开运算也是采用了圆形结构元素

第42行sort_region:Sorting of regions with respect to their relative position.编码排序

4、计算显示

第49行smallest_circle:最小外接圆。计算行列位置、半径、从而实现对焊点区域的大小判断。


Halcon使用技巧:

在【图形窗口】中:按住Ctrl可以查看图中的行列坐标和灰度值。


我们通过第二个案例来继续来熟悉这个处理过程:count_pellets.hdev。

* This programs demonstrates the use of basic morphology
* operators.
* The aim of the program is to detect each single pellet
* (bright particle on a darker background).
*
dev_update_off ()
read_image (Image, 'pellets')
dev_close_window ()
get_image_size (Image, Width, Height)
dev_open_window (0, 0, Width, Height, 'black', WindowID)
dev_set_part (0, 0, Height - 1, Width - 1)
set_display_font (WindowID, 16, 'mono', 'true', 'false')
dev_set_colored (6)
dev_set_draw ('margin')
dev_set_line_width (3)
dev_display (Image)
disp_message (WindowID, 'Detect each single pellet', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowID, 'black', 'true')
stop ()
*
* Segment the regions of the pellets from the background
binary_threshold (Image, LightRegion, 'max_separability', 'light', UsedThreshold)
opening_circle (LightRegion, Region, 3.5)
dev_display (Region)
disp_message (WindowID, 'First, segment the pellets', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowID, 'black', 'true')
stop ()
*
* Compute the connected pellet regions
* Note, that this approach fails, because some of
* the pellets are still connected.
connection (Region, ConnectedRegionsWrong)
dev_display (Image)
dev_display (ConnectedRegionsWrong)
disp_message (WindowID, 'Simple connection fails', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowID, 'black', 'true')
stop ()
*
* Separate each pellet from the others by erosion
erosion_circle (Region, RegionErosion, 7.5)
dev_display (Image)
dev_display (RegionErosion)
disp_message (WindowID, 'Erosion of the pellet regions', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowID, 'black', 'true')
stop ()
*
* Now, compute the connected pellet regions
connection (RegionErosion, ConnectedRegions)
dev_display (Image)
dev_display (ConnectedRegions)
disp_message (WindowID, 'Perform connection now', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowID, 'black', 'true')
stop ()
*
* Turn back to the original pellet size by applying a dilation
dilation_circle (ConnectedRegions, RegionDilation, 7.5)
count_obj (RegionDilation, Number)
dev_display (Image)
dev_display (RegionDilation)
* 求行列坐标和面积。
area_center (RegionDilation, Area, Row, Column)
disp_message (WindowID, Number + ' pellets detected', 'window', 12, 12, 'black', 'true')

还是采集图像,分割、识别、显示计算。


第22行中:binary_threshold (Image, LightRegion, 'max_separability', 'light', UsedThreshold):通过【F1】帮助文档,我们得知:第三个参数为Method。用这个方法来确定阈值:UsedThreshold。函数描述中,指明:两种方法只能用于双峰柱状图。

Both methods should only be used for images that have a bimodal histogram。从图上我们得知:原图冰雹和地面两个实体,颜色灰度值比较容易区分。可以自动确定聚类阈值(本例中程序自动运行为阈值UsedThreshold为112)。

第14行dev_set_draw (Operator):Define the region fill mode.定义填充模式。有两种填充模式:一个是margin和fill模式下。再边缘情况下只显示轮廓: the appearance of the contours can be affected by dev_set_line_width and set_line_style。可以受到后两种算子的影响。第十五行,限制轮廓线的宽度。


fill_up_shape这一步:难以复现:我的思路肯定让halcon限制住了,所以有时间可以重新思考。操作类似与watershed方法锁定焊点临近区,然后在区域内,然后画圆,连通域找圆。select_shape。类似:Hough 圆环变换。找圆。找到之后,区域region编号。

然后最小外接圆、计算中心,半径,显示直径,完成对焊点区域的测量。

import cv2
import numpy as np# 1、加载图像
# 在路径前面加r,即保持字符原始值的意思。相当于C#中的@符号。
img = cv2.imread(r"C:\Users\Public\Documents\MVTec\HALCON-17.12-Progress\examples\images\die\die_03.png")
Bond = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# cv2.imshow("black", Bond)# 2、预处理
_, Bright = cv2.threshold(Bond, 100, 255, cv2.THRESH_BINARY)
# 切割出Die
# Halcon中的通过shape_trans()来覆盖整个二值区域的形状,返回一个指定形状的mask。然后通过reduce_domain()做初步的切割。
# 目的是对大区域的切割。
# OpenCV中我们有两种方法来实现:
# 第一种方法:从非零点实现即可。
# 第二种方法:先闭运算填充白色中的黑点,后查找轮廓,然后通过轮廓近似cv2.approxPolyDP()。
# 补充,若是形状匹配:OpenCV中需要先定轮廓,再拟合。先findContours()得到cnt,然后fit.shape_f(cnt)。
# shape_trans()中第三个参数:
''' 形状:             OpenCV中的函数:convex:             cv2.convexHull()凸包检测ellipse:            cv2.fitEllipse(cnt)outer_circle:       cv2.minEnclosingCircle()inner_circle:       待查找rectangle1:         边界矩形:cv2.boundingRect(cnt)rectangle2:         最小外接矩形:cv2.minAreaRect(cnt)inner_rectangle1:   待查找inner_center:       待查找
'''
# 第一种:非零点查找
tuple_nonzeros = np.array(Bright).nonzero()
x1, x2, y1, y2 = min(tuple_nonzeros[0]), max(tuple_nonzeros[0]), min(tuple_nonzeros[1]), max(tuple_nonzeros[1])
print(x1, x2, y1, y2)   # 坐标的概念和行列概念顺序相反。
img0 = img.copy()  # 避免原图被污染。
Die = cv2.rectangle(img0, (y1, x1), (y2, x2), (0, 255, 0), 3)
# cv2.imshow("Bright", Die)
# 由此得到实际Die区域为mask = Bright[x1:x2, y1:y2]=255
mask = np.zeros(Bond.shape, np.uint8)
mask[x1:x2, y1:y2] = 255
# cv2.imshow("mask", mask)# 第二种:轮廓查找:
# kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))
# closing = cv2.morphologyEx(Bright, cv2.MORPH_CLOSE, kernel, iterations=2)
# # cv2.imshow("closing", closing)
# contours, hierarchy = cv2.findContours(closing, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# cnt = contours[0]
# # print(cnt)
# x, y, w, h = cv2.boundingRect(cnt)
# print(x, y, w, h)
# img0 = img.copy()
# Die2 = cv2.rectangle(img0, (x, y), (x+w, y+h), (0, 255, 0), 3)
# cv2.imshow("margin", Die2)
# # 实际的mask也就是Die的区域为:
# mask = np.zeros(Bond.shape, np.uint8)
# mask[y: y+h, x: x+w] = 255# 两种方法最后差有一个像素误差,因为第二种方法有闭运算,所以首选第一种算法,最精确。
# halcon中对mask填充了颜色以显示,opencv中可以通过[x:x1, y:y1, :] = [0, 255, 0],来实现,
# 也可以通过cv2.floodFill()填充,或者轮廓查找之后通过cv2.drawContours()等。DieGrey = cv2.bitwise_and(Bond, Bond, mask=mask)
# cv2.imshow("DieGrey", DieGrey)# 3、图形分割:
_, Wires = cv2.threshold(DieGrey, 100, 255, cv2.THRESH_BINARY_INV)
# _, Wires1 = cv2.threshold(DieGrey, 100, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
Wires = cv2.bitwise_and(Wires, Wires, mask=mask)
# cv2.imshow("Wires", Wires)
# noise removal
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
opening = cv2.morphologyEx(Wires, cv2.MORPH_OPEN, kernel, iterations=2)
# sure background area
sure_bg = cv2.dilate(opening, kernel, iterations=3)erode = cv2.erode(Wires, kernel, iterations=7)
# cv2.imshow("erode", erode)
# 用于计算图像中每一个非零点距离离自己最近的零点的距离,
# distanceTransform的第二个Mat矩阵参数dst保存了每一个点与最近的零点的距离信息,
# 图像上越亮的点,代表了离零点的距离越远。
dist_transform = cv2.distanceTransform(erode, 1, 5)
# cv2.imshow("temp", dist_transform)
ret, sure_fg = cv2.threshold(dist_transform, 0.6*dist_transform.max(), 255, 0)
cv2.imshow("sure_fg", sure_fg)
# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)  # 图像相减
# cv2.imshow('unknown', unknown)# Marker labelling
_, markers1 = cv2.connectedComponents(sure_fg)# Add one to all labels so that sure background is not 0, but 1
# 把将背景标 为 0 其他的对 使用从 1 开始的正整数标
markers = markers1 + 1
# Now, mark the region of unknown with zero
markers[unknown == 255] = 0markers3 = cv2.watershed(img, markers)
print(markers3.shape)
cv2.imshow("markers", ret)
img[markers3 == -1] = [255, 0, 0]
cv2.imshow("WatarShed", img)# halcon中通过fill_up_shape (Wires, WiresFilled, 'area', 1, 100)函数通过给定的形状,
# 来计算面积或者轮廓特征,以此来匹配目标,进一步靠近我们关系的区域。
# 主旨思路就是一步步靠近我们的目标区域。
# 在深度学习中可以通过Pix2Pix算法,用PS标注数据集来实现。
# # 经过实测:用计算轮廓面积方法需要先经过膨胀腐蚀,断开区域之间的连同独立区域之后。再计算面积来着色分割。这个过程就是水漫法。
# contours1, hierarchy1 = cv2.findContours(Wires, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# for cnt in contours1:
#     s = cv2.contourArea(cnt)
#     if (s > 100) & (s < 1000):
#         # print(s)
#         cv2.drawContours(img, [cnt], -1, (0, 0, 255), 3)
# cv2.imshow("filled up", img)# 类似于OpenCV找硬币分割中的方法,通过水漫法(分水岭法)来分割目标。cv2.waitKey(0)
cv2.destroyAllWindows()

(一)掰开了,揉碎了,说经典halcon中的那些算子相关推荐

  1. XElement.Load 需要释放吗_奥施康定掰开后能当即释片用吗?

    文. 小山丘的旅行 为了更好的对待.接受并合理应用止痛药,我们论坛专门开设了4个"止痛群".两年多来,我们一起面对了各种癌痛的艰难:药物的难以接受.用药的调整和难治性疼痛的处理.药 ...

  2. Halcon中的基于区域的形态学处理(腐蚀膨胀开闭预算顶底帽运算)

    形态学处理的作用: 用于提取有意义的局部图像细节,通过改变局部区域的像素形态,对图像进行增强,为后续分割.特征提取.边缘检测做准备. 在开始之前,我们先了解一下:结构元素:StructElement ...

  3. 解决loadrunner 12 录制时打不开Chrome谷歌浏览器,显示正在加载中的问题

    解决loadrunner 12 录制时打不开Chrome谷歌浏览器,显示正在加载中的问题 刚开始学习loadrunner,安装了loadrunner 12,录制时浏览器一直显示正在加载- 看到网上有人 ...

  4. 跟眼睛开个玩笑:15幅经典的强迫透视摄影作品

    强迫透视(Forced perspective)是一种摄影技巧,利用光学和人眼视觉感知的错觉,使得被拍摄物体看起来比实际更远,更近,更大或者更小,利用被拍物体与周围环境的相对性形成有趣的关联,再加上摄 ...

  5. 别再被三次握手和四次挥手所支配!把TCP这玩意儿给你掰开了说

    本文生动形象地展示了TCP/IP协议中三次握手的过程,可耐心阅读 你是一台电脑,你的名字叫 A 你知道另一位伙伴 B的 IP 地址,且你们之间的网络是通的,无论多远,你都可以将一个数据包发送给你的伙伴 ...

  6. mongodb还不会?万字长文解析揉碎了给你讲,收藏这一篇就够了

    大家好,我是辣条. 目录 Mongodb的的增删改查 1. mongodb插入数据 2. mongodb的保存 3 mongodb的查询 4 mongodb的更新 5 mongodb的删除 mongo ...

  7. python可以开多少线程_Python开启线程,在函数中开线程的实例

    逻辑处理上分成了多个模块,为了提高效率,前一个模块处理完调用后一个模块操作时使用多线程 我这里遇到的情形是前面取数据后面存到mysql,发现单线程效率很低,改为取数据后开线程存到mysql 开启线程之 ...

  8. 解决打不开 RSA 密钥容器 即:加密web.config中的内容

    简单的解决方法: WebConfig 加解密,未能使用提供程序"RsaProtectedConfigurationProvider"进行解密.提供程序返回错误消息为: 打不开 RS ...

  9. MC开服教程3:python提取日志中的聊天记录、登录信息、死亡信息、成就信息

    零.前言 系列教程 MC开服教程1:简略版使用阿里云部署mc服务器(paper端) MC开服教程2:材质包法自定义唱片音乐 一.总介绍 在云端部署好多人服务器后,mc的logs文件夹里面记录了游戏的日 ...

最新文章

  1. python类的私有属性_Python 的私有属性和‘受保护的’属性
  2. 树莓派保卫战--防止SSH暴力破解
  3. 记录SQL server学习的存储过程的摘录
  4. java创建图片文件怎么打开_java 程序怎么打开一张图片?
  5. Eclipse-Mybatis-generatorConfig.xml
  6. 项目管理工具 web_14个用于改善项目的Web工具
  7. java调用perl脚本_Java中调用Perl脚本的应用
  8. 量化指标公式源码_五行量化副图指标公式源码
  9. 重装系统后没有网卡驱动
  10. 傅里叶(一):傅里叶分析
  11. html如何设置自动点击事件,html 如何设置打开网页时自动触发按钮的单击事件
  12. Java学习(8) —— 异常处理
  13. Programming-寻找发贴水王(C)
  14. ESP32 HTTP Client接口使用
  15. C语言 实现 面向对象编程 OOC
  16. C4.5(决策树预测)算法
  17. CMake和Make之间的区别
  18. My shortcomings | 我的不足
  19. 【笔记】openwrt - 【一文解决】ipv6设置、DDNS、端口转发
  20. 微软应用商店_微软:关于UWP平台,我们知道错了

热门文章

  1. 【报错】亲测有用,copytranslator只显示部分翻译结果
  2. 2020年产品经理职业发展路径
  3. 2022-2028年中国手机结构件行业市场发展规模及市场前景趋势报告
  4. 自己动手iPad贴膜小记
  5. 《教妹学数据库系统》(五)逻辑数据库设计(上)
  6. 红黑树的历史和由来。
  7. 人生到处知何似,应似飞鸿踏雪泥
  8. 三维重建(一)外极几何,基础矩阵及求解
  9. 川土微CA-IF1051 CAN收发器通过AEC-Q100 Grade 1认证
  10. MySQL数据库安全