OpenCV-直方图
bigegpt 2024-11-20 12:39 4 浏览
直方图
如何使用OpenCV和Numpy函数查找直方图,如何使用OpenCV和Matplotlib函数绘制直方图
cv.calcHist(),np.histogram()
什么是直方图:
您可以将直方图视为图形或绘图,从而可以总体了解图像的强度分布。它是在X轴上具有像素值(不总是从0到255的范围),在Y轴上具有图像中相应像素数的图
这只是理解图像的另一种方式。通过查看图像的直方图,您可以直观地了解该图像的对比度,亮度,强度分布等。当今几乎所有图像处理工具都提供直方图功能。
您可以看到图像及其直方图。(请记住,此直方图是针对灰度图像而非彩色图像绘制的)。直方图的左侧区域显示图像中较暗像素的数量,而右侧区域则显示明亮像素的数量。从直方图中,您可以看到暗区域多于亮区域,而中间调的数量(中间值的像素值,例如127附近)则非常少。
如何寻找直方图:
现在我们有了一个关于直方图的想法,我们可以研究如何找到它。OpenCV和Numpy都为此内置了功能。在使用这些功能之前,我们需要了解一些与直方图有关的术语。
BINS:上面的直方图显示每个像素值的像素数,即从0到255。即,您需要256个值来显示上面的直方图。但是考虑一下,如果您不需要分别找到所有像素值的像素数,而是找到像素值间隔中的像素数怎么办? 例如,您需要找到介于0到15之间的像素数,然后找到16到31之间,…,240到255之间的像素数。只需要16个值即可表示直方图。这就是在OpenCV教程中有关直方图的示例中显示的内容。
因此,您要做的就是将整个直方图分成16个子部分,每个子部分的值就是其中所有像素数的总和。 每个子部分都称为“ BIN”。在第一种情况下,bin的数量为256个(每个像素一个),而在第二种情况下,bin的数量仅为16个。BINS由OpenCV文档中的histSize术语表示。
DIMS:这是我们为其收集数据的参数的数量。在这种情况下,我们仅收集关于强度值的一件事的数据。所以这里是1。
RANGE:这是您要测量的强度值的范围。通常,它是[0,256],即所有强度值。
01 OpenCV 中的直方图计算:
因此,现在我们使用cv.calcHist()函数查找直方图。让我们熟悉一下该函数及其参数:cv.calcHist(images,channels,mask,histSize,ranges [,hist [,accumulate]])
- images:它是uint8或float32类型的源图像。它应该放在方括号中,即“ [img]”。
- channels:也以方括号给出。它是我们计算直方图的通道的索引。例如,如果输入为灰度图像,则其值为[0]。对于彩色图像,您可以传递[0],[1]或[2]分别计算蓝色,绿色或红色通道的直方图。
- mask:图像掩码。为了找到完整图像的直方图,将其指定为“无”。但是,如果要查找图像特定区域的直方图,则必须为此创建一个掩码图像并将其作为掩码。
- histSize:这表示我们的BIN计数。需要放在方括号中。对于全尺寸,我们通过[256]。
- ranges:这是我们的RANGE。通常为[0,256]。
因此,让我们从示例图像开始。只需以灰度模式加载图像并找到其完整直方图即可。
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv.imread('images/0.jpg',cv.IMREAD_GRAYSCALE)
hist = cv.calcHist([img], [0], None, [256], [0, 256])
# print(hist.shape) # (256, 1) # 每个值对应于该图像中具有相应像素值的像素数
# 绘制直方图
plt.plot(hist)
plt.show()
02 Numpy中的直方图计算:
Numpy还为您提供了一个函数np.histogram()。因此,除了calcHist()函数外,您可以尝试下面的代码:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv.imread('images/0.jpg', cv.IMREAD_GRAYSCALE)
# 1
# hist = cv.calcHist([img], [0], None, [256], [0, 256])
# # print(hist.shape) # (256, 1) # 每个值对应于该图像中具有相应像素值的像素数
# # 绘制直方图
# plt.plot(hist)
# plt.show()
# 2
# hist, bins = np.histogram(img.ravel(), 256, [0, 256]) # img.ravel() 的作用是降维
# # print(img.shape) # (1080, 1920)
# # print(img.ravel().shape) # (2073600,)
# plt.plot(hist)
# plt.show()
# 另外 Numpy还有另一个函数np.bincount(),它比np.histogram()快10倍左右,对于一维直方图,您可以更好地尝试一下
hist = np.bincount(img.ravel(), minlength=256)
plt.plot(hist)
plt.show()
如何绘制直方图:
两种方法:
1. 简洁有力的方法:使用Matplotlib绘图功能
2. 稍长的方法:使用OpenCV绘图功能(cv.line或cv.polyline函数,具体略)
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv.imread('images/0.jpg', 0)
plt.hist(img.ravel(), 256, [0,256]) # Matplotlib带有直方图绘图功能:matplotlib.pyplot.hist() 它直接找到直方图并将其绘制。您无需使用calcHist()或np.histogram()函数来查找直方图
plt.show()
掩码的使用:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv.imread('images/0.jpg', 0)
# create a mask
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
masked_img = cv.bitwise_and(img, img, mask=mask)
# 计算掩码区域和非掩码区域的直方图
# 检查作为掩码的第三个参数
hist_full = cv.calcHist([img], [0], None, [256], [0, 256])
hist_mask = cv.calcHist([img], [0], mask, [256], [0, 256])
plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask, 'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0, 256])
plt.show()
直方图均衡:
将学习直方图均衡化的概念,并利用它来提高图像的对比度
直方图均衡化是图像处理领域中利用图像直方图对对比度进行调整的方法
概述:
这种方法通常用来增加许多图像的全局对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。
这种方法对于背景和前景都太亮或者太暗的图像非常有用,这种方法尤其是可以带来X光图像中更好的骨骼结构显示以及曝光过度或者曝光不足照片中更好的细节。这种方法的一个主要优势是它是一个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图,并且计算量也不大。这种方法的一个缺点是它对处理的数据不加选择,它可能会增加背景噪声的对比度并且降低有用信号的对比度。
均衡化前后的图像的直方图
例子:
下面的这个例子是一个8位的8×8灰度图像:
该灰度图像的灰度值出现次数如下表所示,为了简化表格,出现次数为0的值已经被省略
累积分布函数(cdf)如下所示,与上一表格类似,为了简化,累积分布函数值为0的灰度值已经被省略
代码:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv.imread('images/aaa.jpg', cv.IMREAD_GRAYSCALE)
hist, bins = np.histogram(img.flatten(), 256, [0, 256])
cdf = hist.cumsum() # shape (256,1)
cdf_normalized = cdf / cdf.max() * float(hist.max())
plt.plot(cdf_normalized, color='b')
plt.hist(img.flatten(), 256, [0, 256], color='r')
plt.xlim([0, 256])
plt.legend(('cdf', 'histogram'), loc='upper left')
plt.show()
你可以看到直方图位于较亮的区域。我们需要全频谱。为此,我们需要一个转换函数,将亮区域的输入像素映射到整个区域的输出像素。这就是直方图均衡化的作用
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv.imread('images/aaa.jpg', cv.IMREAD_GRAYSCALE)
equ = cv.equalizeHist(img)
plt.subplot(1, 2, 1), plt.imshow(img, 'gray')
plt.title("img"), plt.xticks([]), plt.yticks([])
plt.subplot(1, 2, 2), plt.imshow(equ, 'gray')
plt.title("equ"), plt.xticks([]), plt.yticks([])
plt.show()
当图像的直方图限制在特定区域时,直方图均衡化效果很好。在直方图覆盖较大区域(即同时存在亮像素和暗像素)的强度变化较大的地方,效果不好。
CLAHE 自适应直方图均衡
直方图均衡后,背景对比度确实得到了改善。但是在两个图像中比较雕像的脸。由于亮度过高,我们在那里丢失了大多数信息。这是因为它的直方图不像我们在前面的案例中所看到的那样局限于特定区域(尝试绘制输入图像的直方图,您将获得更多的直觉)。
因此,为了解决这个问题,使用了自适应直方图均衡。在这种情况下,图像被分成称为“tiles”的小块(在OpenCV中,tileSize默认为8x8)。然后,像往常一样对这些块中的每一个进行直方图均衡。因此,在较小的区域中,直方图将限制在一个较小的区域中(除非存在噪声)。如果有噪音,它将被放大。为了避免这种情况,应用了对比度限制。如果任何直方图bin超出指定的对比度限制(在OpenCV中默认为40),则在应用直方图均衡之前,将这些像素裁剪并均匀地分布到其他bin。均衡后,要消除图块边界中的伪影,请应用双线性插值。
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv.imread('images/aaa.jpg', cv.IMREAD_GRAYSCALE)
equ = cv.equalizeHist(img)
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
cl1 = clahe.apply(img)
plt.subplot(2, 2, 1), plt.imshow(img, 'gray')
plt.title("img"), plt.xticks([]), plt.yticks([])
plt.subplot(2, 2, 2), plt.imshow(equ, 'gray')
plt.title("equ"), plt.xticks([]), plt.yticks([])
plt.subplot(2, 2, 3), plt.imshow(cl1, 'gray')
plt.title("cl1"), plt.xticks([]), plt.yticks([])
plt.show()
二维直方图:
学习查找和绘制2D直方图
在之前,我们计算并绘制了一维直方图。 之所以称为一维,是因为我们仅考虑一个特征,即像素的灰度强度值。
但是在二维直方图中,您要考虑两个特征是每个像素的色相(色调)和饱和度值。
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv.imread('images/0.jpg')
hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
hist = cv.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])
# channel = [0,1],因为我们需要同时处理H和S平面
# bins = [180,256] 对于H平面为180,对于S平面为256
# channel = [0,1],因为我们需要同时处理H和S平面
# range = [0,180,0,256] 色相(调)值介于0和180之间,饱和度介于0和256之间
plt.imshow(hist, interpolation='nearest') # X轴显示S值,Y轴显示色相
plt.show()
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv.imread('images/0.jpg')
hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
# Numpy 中的二维直方图 np.histogram2d h s
hist, xbins, ybins = np.histogram2d(hsv[...,0].ravel(), hsv[...,1].ravel(), [180, 256], [[0, 180], [0, 256]])
# 第一个参数是H平面,第二个是S平面,第三个是对于H平面为180,对于S平面为256,第四个是它们的范围。
plt.imshow(hist, interpolation='nearest') # X轴显示S值,Y轴显示色相
plt.show()
直方图反投影:
略
傅里叶变换
使用OpenCV查找图像的傅立叶变换
利用Numpy中可用的fft (快速傅立叶变换)函数
cv.dft(),cv.idft(),
dft: 离散傅里叶变换
它是一种线性积分变换,用于信号在时域(或空域)和频域之间的变换。
而又知:
任何连续的周期信号,都可以由一组适当的正弦曲线组合而成 ---傅里叶。
所以,任何连续的周期信号都是可以用频率来表示的,
相位:
不是同时开始的一组三角函数,在叠加时要体现开始的时间,
图像上的傅里叶变换
您可以将图像视为在两个方向上采样的信号。因此,在X和Y方向都进行傅立叶变换,可以得到图像的频率表示。更直观地说,对于正弦信号,如果幅度在短时间内变化如此之快,则可以说它是高频信号。如果变化缓慢,则为低频信号。您可以将相同的想法扩展到图像。图像中的振幅在哪里急剧变化?在边缘点或噪声。因此,可以说边缘和噪声是图像中的高频内容。如果幅度没有太大变化,则它是低频分量。
傅里叶变换得到低频和高频信息,低频针对的是图片的细节,高频针对的是图片的边界,我们对频率进行处理,最终会反映到逆变换后的图像上。
如何找到傅立叶变换:
Numpy进行傅立叶变换:
Numpy具有FFT软件包来执行此操作。np.fft.fft2()为我们提供了频率转换,它将是一个复杂的数组。
它的第一个参数是输入图像,即灰度图像。
第二个参数是可选的,它决定输出数组的大小。如果它大于输入图像的大小,则在计算FFT之前用零填充输入图像。如果小于输入图像,将裁切输入图像。如果未传递任何参数,则输出数组的大小将与输入的大小相同。
现在,一旦获得结果,零频率分量(DC分量)将位于左上角。如果要使其居中,则需要在两个方向上将结果都移动N2N2。只需通过函数np.fft.fftshift()即可完成。(它更容易分析)。找到频率变换后,就可以找到幅度谱。
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv.imread('images/0.jpg',cv.IMREAD_GRAYSCALE)
f = np.fft.fft2(img) # 傅里叶变换 # 返回值是一个复数的数组
# print(type(f),type(f[0,0])) # <class 'numpy.ndarray'> <class 'numpy.complex128'>
fshift = np.fft.fftshift(f) # 将零频率分量移动到中心位置
magnitude_spectrum = 20 * np.log(np.abs(fshift)) # 调整值的范围
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
看,您可以在中心看到更多白色区域,这表明低频内容更多 .
Numpy 实现逆傅里叶变换
np.fft.ifft2() , np.fft.ifftshift()
低频,高频
滤波
接收一定的频率
高通滤波器:允许高频通过,将会增强图片尖锐的细节
低通滤波器:允许低频通过 ,将会模糊图片
代码
1
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv.imread('images/lena.jpg', cv.IMREAD_GRAYSCALE)
row, col = img.shape
crow, ccol = row // 2, col // 2
f = np.fft.fft2(img) # 傅里叶变换 # 返回值是一个复数的数组
fshift = np.fft.fftshift(f) # 将零频率分量移动到中心位置
# 去掉低频,将白色的去掉
fshift[crow - 30:crow + 30, ccol - 30: ccol + 30] = 0
# 逆变换回 图片
ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
iimg = np.abs(iimg)
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('img'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(iimg, cmap='gray')
plt.title('iimg'), plt.xticks([]), plt.yticks([])
plt.show()
2
具体操作:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv.imread('images/lena.jpg', cv.IMREAD_GRAYSCALE)
row, col = img.shape
crow, ccol = row // 2, col // 2
mask = np.zeros((row, col), np.uint8)
mask[crow - 30:crow + 30, ccol - 30:ccol + 30] = 1
f = np.fft.fft2(img) # 傅里叶变换 # 返回值是一个复数的数组
fshift = np.fft.fftshift(f) # 将零频率分量移动到中心位置
fshift = fshift * mask
# 逆变换回 图片
ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
iimg = np.abs(iimg)
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('img'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(iimg, cmap='gray')
plt.title('iimg'), plt.xticks([]), plt.yticks([])
plt.show()
模板匹配
如何使用模板匹配在图像中查找对象,cv.matchTemplate(),cv.minMaxLoc()
理论:
模板匹配是一种用于在较大图像中搜索和查找模板图像位置的方法。
为此,OpenCV带有一个函数cv.matchTemplate()。 它只是将模板图?像滑动到输入图像上(就像在2D卷积中一样),然后在模板图像下比较模板和输入图像的拼图。
它返回一个灰度图像,其中每个像素表示该像素的邻域与模板匹配的程度。
如果输入图像的大小为(WxH),而模板图像的大小为(wxh),则输出图像的大小将为(W-w + 1,H-h + 1)。得到结果后,可以使用cv.minMaxLoc()函数查找最大/最小值在哪。将其作为矩形的左上角,并以(w,h)作为矩形的宽度和高度。该矩形是您模板的区域。
OpenCV中的模板匹配
我们在图1 中搜索车牌,
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
img = cv.imread('images/aaa.jpg')
imgGray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
img2 = imgGray.copy()
template = cv.imread('images/template.jpg', cv.IMREAD_GRAYSCALE)
h, w = template.shape
# 列表中所有的6种比较方法
methods = ['cv.TM_CCOEFF', 'cv.TM_CCOEFF_NORMED', 'cv.TM_CCORR',
'cv.TM_CCORR_NORMED', 'cv.TM_SQDIFF', 'cv.TM_SQDIFF_NORMED']
for meth in methods:
temp = img2.copy()
temp2 = img.copy()
method = eval(meth)
# 应用模板匹配
res = cv.matchTemplate(temp, template, method)
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
# 如果方法是TM_SQDIFF或TM_SQDIFF_NORMED,则取最小值
if method in [cv.TM_SQDIFF, cv.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv.rectangle(temp, top_left, bottom_right, (255, 255, 255), 2)
cv.rectangle(temp2, top_left, bottom_right, (0, 255, 0), 2)
plt.subplot(221), plt.imshow(res, cmap='gray')
plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
plt.subplot(222), plt.imshow(temp, cmap='gray')
plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
plt.subplot(223), plt.imshow(temp2[..., ::-1])
plt.title('Detected Point(color)'), plt.xticks([]), plt.yticks([])
plt.suptitle(meth) # 设置大标题
plt.show()
你会看到,使用cv.TM_CCORR的结果并不理想
多对象的模板匹配
在上面,我们在图像中搜索了车牌,该车牌在图像中仅出现一次。假设您正在搜索具有多次出现的对象,则cv.minMaxLoc()不会为您提供所有位置。在这种情况下,我们将使用阈值化。
因此,在此示例中,我们将使用著名游戏超级玛丽的屏幕截图,并在其中找到硬币
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
if __name__ == '__main__':
img_rgb = cv.imread('mario.png')
img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)
template = cv.imread('mario_coin.png', 0)
h, w = template.shape
res = cv.matchTemplate(img_gray, template, cv.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where(res >= threshold) # 返回的是个元组,其中的元素是两个array,zip 之后就是对应的坐标了
for pt in zip(*loc[::-1]):
cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)
cv.imwrite('res.png', img_rgb)
# arr = np.array([[1,2],[3,4]])
# print(arr)
# ret = np.where(arr>=2)
# for point in zip(*ret):
# print(point)
点击领取Qt学习资料+视频教程~「链接」
- 上一篇:LLM中对于非结构化 PDF 文本提取技术
- 下一篇:什么?Pod控制器你还不会?
相关推荐
- 悠悠万事,吃饭为大(悠悠万事吃饭为大,什么意思)
-
新媒体编辑:杜岷赵蕾初审:程秀娟审核:汤小俊审签:周星...
- 高铁扒门事件升级版!婚宴上‘冲喜’老人团:我们抢的是社会资源
-
凌晨两点改方案时,突然收到婚庆团队发来的视频——胶东某酒店宴会厅,三个穿大红棉袄的中年妇女跟敢死队似的往前冲,眼瞅着就要扑到新娘的高额钻石项链上。要不是门口小伙及时阻拦,这婚礼造型团队熬了三个月的方案...
- 微服务架构实战:商家管理后台与sso设计,SSO客户端设计
-
SSO客户端设计下面通过模块merchant-security对SSO客户端安全认证部分的实现进行封装,以便各个接入SSO的客户端应用进行引用。安全认证的项目管理配置SSO客户端安全认证的项目管理使...
- 还在为 Spring Boot 配置类加载机制困惑?一文为你彻底解惑
-
在当今微服务架构盛行、项目复杂度不断攀升的开发环境下,SpringBoot作为Java后端开发的主流框架,无疑是我们手中的得力武器。然而,当我们在享受其自动配置带来的便捷时,是否曾被配置类加载...
- Seata源码—6.Seata AT模式的数据源代理二
-
大纲1.Seata的Resource资源接口源码2.Seata数据源连接池代理的实现源码3.Client向Server发起注册RM的源码4.Client向Server注册RM时的交互源码5.数据源连接...
- 30分钟了解K8S(30分钟了解微积分)
-
微服务演进方向o面向分布式设计(Distribution):容器、微服务、API驱动的开发;o面向配置设计(Configuration):一个镜像,多个环境配置;o面向韧性设计(Resista...
- SpringBoot条件化配置(@Conditional)全面解析与实战指南
-
一、条件化配置基础概念1.1什么是条件化配置条件化配置是Spring框架提供的一种基于特定条件来决定是否注册Bean或加载配置的机制。在SpringBoot中,这一机制通过@Conditional...
- 一招解决所有依赖冲突(克服依赖)
-
背景介绍最近遇到了这样一个问题,我们有一个jar包common-tool,作为基础工具包,被各个项目在引用。突然某一天发现日志很多报错。一看是NoSuchMethodError,意思是Dis...
- 你读过Mybatis的源码?说说它用到了几种设计模式
-
学习设计模式时,很多人都有类似的困扰——明明概念背得滚瓜烂熟,一到写代码就完全想不起来怎么用。就像学了一堆游泳技巧,却从没下过水实践,很难真正掌握。其实理解一个知识点,就像看立体模型,单角度观察总...
- golang对接阿里云私有Bucket上传图片、授权访问图片
-
1、为什么要设置私有bucket公共读写:互联网上任何用户都可以对该Bucket内的文件进行访问,并且向该Bucket写入数据。这有可能造成您数据的外泄以及费用激增,若被人恶意写入违法信息还可...
- spring中的资源的加载(spring加载原理)
-
最近在网上看到有人问@ContextConfiguration("classpath:/bean.xml")中除了classpath这种还有其他的写法么,看他的意思是想从本地文件...
- Android资源使用(android资源文件)
-
Android资源管理机制在Android的开发中,需要使用到各式各样的资源,这些资源往往是一些静态资源,比如位图,颜色,布局定义,用户界面使用到的字符串,动画等。这些资源统统放在项目的res/独立子...
- 如何深度理解mybatis?(如何深度理解康乐服务质量管理的5个维度)
-
深度自定义mybatis回顾mybatis的操作的核心步骤编写核心类SqlSessionFacotryBuild进行解析配置文件深度分析解析SqlSessionFacotryBuild干的核心工作编写...
- @Autowired与@Resource原理知识点详解
-
springIOCAOP的不多做赘述了,说下IOC:SpringIOC解决的是对象管理和对象依赖的问题,IOC容器可以理解为一个对象工厂,我们都把该对象交给工厂,工厂管理这些对象的创建以及依赖关系...
- java的redis连接工具篇(java redis client)
-
在Java里,有不少用于连接Redis的工具,下面为你介绍一些主流的工具及其特点:JedisJedis是Redis官方推荐的Java连接工具,它提供了全面的Redis命令支持,且...
- 一周热门
- 最近发表
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- resize函数 (64)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- mybatis大于等于 (64)
- xcode-select (66)
- mysql授权 (74)
- 下载测试 (70)
- linuxlink (65)
- pythonwget (67)
- androidinclude (65)
- logstashinput (65)
- hadoop端口 (65)
- vue阻止冒泡 (67)
- oracle时间戳转换日期 (64)
- jquery跨域 (68)
- php写入文件 (73)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)