OpenCV之信用卡识别实战

这篇具有很好参考价值的文章主要介绍了OpenCV之信用卡识别实战。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

代码

链接: https://pan.baidu.com/s/1KjdiqkyYGfHk97wwgF-j3g?pwd=hhkf 提取码: hhkf

视频讲解

链接: https://pan.baidu.com/s/1PZ6w5NcSOuKusBTNa3Ng2g?pwd=79wr 提取码: 79wr

模板匹配文件

OpenCV之信用卡识别实战,CV&NLP学习,# ———基础入门系列,opencv,人工智能,计算机视觉文章来源地址https://www.toymoban.com/news/detail-630671.html

主程序(ocr_template_match.py)

# 导入工具包
from imutils import contours # 从imutils库导入contours模块,imutils是一个方便的图像处理库,contours模块主要用于处理和操作图像轮廓。
import numpy as np
import argparse # 处理命令行参数
import cv2
import myutils

# 设置参数
ap = argparse.ArgumentParser() # 创建一个ArgumentParser对象,这个对象会保存命令行参数和程序文档等信息

# 添加一个命令行参数,参数的短名称是"-i",长名称是"--image",这个参数是必须的(required=True),参数的含义是输入图像的路径。
ap.add_argument("-i", "--image", required=True,
	help="path to input image")

# 添加另一个命令行参数,参数的短名称是"-t",长名称是"--template",这个参数也是必须的,参数的含义是模板图像的路径。
# 这个模板图像是OCR字体的图像,其中包含了0-9的数字。
ap.add_argument("-t", "--template", required=True,
	help="path to template OCR-A image")

# 解析命令行参数,然后将结果转为一个字典,字典的键是参数的名称,值是参数的值。
args = vars(ap.parse_args())
print('\n', args) # {'image': 'images/credit_card_03.png', 'template': 'images/ocr_a_reference.png'}

# 指定信用卡类型
"""
定义了一个名为FIRST_NUMBER的字典,这个字典中的键是信用卡卡号的首位数字的字符串形式,对应的值是信用卡的类型。
这是因为信用卡的种类可以通过卡号的首位数字来区分。
比如credit_card_03.png里面的信用卡的首位数字是5,那么这张信用卡就是MasterCard
"""
FIRST_NUMBER = {
	"3": "American Express",
	"4": "Visa",
	"5": "MasterCard",
	"6": "Discover Card"
}
# 绘图展示函数
def cv_show(name,img):
	cv2.imshow(name, img) # name: 窗口名称; img: 要展示的图像
	cv2.waitKey(0)
	cv2.destroyAllWindows()
	cv2.waitKey(1) # 对于MacOS系统,cv2.waitKey(1)是必要的,用于处理一些特定的系统事件,但在Windows上不一定需要。

# 读取一个模板图像。使用OpenCV的imread函数读取模板图像,图像的路径从前面解析的命令行参数args中获取。
img = cv2.imread(args["template"])
cv_show('img',img)

# 灰度图。将模板图像转换为灰度图像,使用OpenCV的cvtColor函数,COLOR_BGR2GRAY表示从BGR颜色空间转换到灰度空间。
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv_show('ref',ref) # 展示灰度图像


"""
将灰度图像转换为二值图像,使用OpenCV的threshold函数。
10是阈值,255是当像素值高于(对于THRESH_BINARY_INV)或者小于(对于THRESH_BINARY)阈值时应给予的新的像素值 ,
THRESH_BINARY_INV表示进行反二进制阈值化(低于阈值的像素设置为255,高于阈值的像素设置为0)。
"""
ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]
cv_show('ref',ref) # 展示二值图像


"""
计算轮廓
使用OpenCV的findContours函数计算二值图像的轮廓,RETR_EXTERNAL表示只检测外轮廓,CHAIN_APPROX_SIMPLE表示只保留终点坐标
返回的refCnts中每个元素都是图像中的一个轮廓
"""
refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
"""
cv2.drawContours函数用来在图像上画出找到的轮廓。第一个参数img是要绘制轮廓的图像,第二个参数refCnts是从前面找到的轮廓列表,
第三个参数-1表示要绘制所有轮廓,(0,0,255)是轮廓的颜色(这里是红色),3是线宽。
"""
cv2.drawContours(img, refCnts, -1, (0, 0, 255), 3)
cv_show('img', img)  # 展示绘制了轮廓的图像

"""
refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0] 这行代码的主要作用是对模板图像中的轮廓进行排序。

在这里,myutils.sort_contours(refCnts, method="left-to-right")[0] 是调用 sort_contours 函数,对 refCnts(模板图像中的轮廓)进行排序。

method="left-to-right" 参数表示轮廓应该按照从左到右的顺序排序。这对于在图像中识别和分类对象(如数字)时非常有用,因为我们通常会按照从左到右的顺序进行阅读和识别。

sort_contours 函数的返回值是一个元组,其中包含两个元素:排序后的轮廓和对应的边界框。由于我们只关心排序后的轮廓,所以使用 [0] 索引来获取第一个元素,即排序后的轮廓。

因此,这行代码的结果 refCnts 是一个列表,其中的轮廓已经按照从左到右的顺序进行了排序。这样处理之后,程序可以按照这个顺序逐个处理和识别每个数字。
"""
refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0] # 排序,从左到右,从上到下
# cv2.drawContours(img, refCnts, 0, (255, 0, 0), 2)
# cv_show('img', img) # 同学们这里可以修改method看看输出会有什么区别


digits = {} # 定义一个空字典digits,将用来存储每个数字模板。
# 遍历每一个轮廓
for (i, c) in enumerate(refCnts): # 遍历轮廓列表 refCnts。在每一次循环中,索引 i 和对应的轮廓 c 都被提取出来。
	# 计算外接矩形并且resize成合适大小
	(x, y, w, h) = cv2.boundingRect(c) # 对于每一个轮廓 c,计算其外接矩形,外接矩形的坐标被存储在 (x, y) 中,矩形的宽度和高度分别是 w 和 h
	# 使用刚刚计算出来的外接矩形的坐标和大小,从灰度图像 ref 中提取出对应的区域,这就是我们的 ROI。
	# 在OpenCV和很多其他图像处理库中,图像的索引方式通常为 [y:y+h, x:x+w],这样的顺序:先行(高度)后列(宽度)
	roi = ref[y:y + h, x:x + w]
	roi = cv2.resize(roi, (57, 88)) # 调整 ROI 的大小,使得每一个数字模板的大小都是一致的(这里是 57x88 像素)。

	# 将提取和调整大小后的 ROI 存储在字典 digits 中,字典的键是数字的索引 i,值是对应的数字模板。
	digits[i] = roi

# 初始化卷积核
# 这两行代码生成了两个矩形的结构元素(也称为卷积核或结构核),分别为9x3和5x5的大小。这些结构元素将在接下来的形态学操作中使用。
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

#读取输入图像,预处理
image = cv2.imread(args["image"])
cv_show('image',image)
image = myutils.resize(image, width=300) # 用自定义的resize函数将图像的宽度缩放到300像素,高度按比例缩放
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 将缩放后的彩色图像转换为灰度图像。在OpenCV中,颜色图像通常是BGR格式,而在很多图像处理任务中,我们只需要灰度图像。
cv_show('gray',gray)


# 礼帽操作:原始输入-开运算(先腐蚀,在膨胀)的结果,突出更明亮的区域;黑帽操作常常用于强调比周围暗的区域,或者是强调比较小,且比周围区域暗的细节部分。
# 这行代码对灰度图像执行了一个名为"礼帽"的形态学操作,这是通过使用前面定义的9x3的矩形卷积核对图像进行开运算,然后从原始图像中减去结果来实现的
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel) 
cv_show('tophat',tophat)

# 这行代码对进行了"礼帽"操作的图像应用Sobel算子,以计算图像的x方向(水平方向)的梯度。
# 这里ksize=-1表示使用3x3的Sobel滤波器。
gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, #ksize=-1相当于用3*3的
	ksize=-1)
gradX = np.absolute(gradX) # 这行代码将Sobel梯度的值转换为绝对值,因为梯度值可能是正值也可能是负值,转换为绝对值使所有梯度值都为正,方便后续处理。
"""
这三行代码对梯度图像进行了归一化和量化处理。
首先找到梯度图像的最小值和最大值,然后将梯度图像的亮度值线性映射到0-255的范围,以便显示和保存。
最后,将浮点型的梯度图像转换为8位无符号整型。
"""
(minVal, maxVal) = (np.min(gradX), np.max(gradX))
gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
gradX = gradX.astype("uint8")
print (np.array(gradX).shape) # 这行代码打印出处理后的梯度图像的形状(尺寸),包括高度和宽度。
cv_show('gradX',gradX)

# 通过闭操作(先膨胀,再腐蚀)将数字连在一起
# 使用闭操作来连结图像中的数字。闭操作是先进行膨胀,然后进行腐蚀。这样可以将断开的部分连在一起,主要用来关闭前景物体内部的小孔或者小黑点。这里使用的是前面定义的rectKernel,一个长方形的结构元素。
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel) 
cv_show('gradX',gradX)

"""
使用阈值化操作来将图像转换为二值图像。其中,cv2.THRESH_BINARY表示大于阈值的像素点设为最大值(这里是255),小于阈值的设为0;
cv2.THRESH_OTSU表示使用Otsu算法来自动确定最优阈值,该方法适合对于双峰图像,需要将阈值参数设置为0。
输出的thresh是一个二值化后的图像。
"""
thresh = cv2.threshold(gradX, 0, 255,
	cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] 
cv_show('thresh',thresh)

# 再进行一次闭操作。这次使用的结构元素是sqKernel,一个正方形的结构元素,其目的是使得图像中的数字更加紧密,减小数字间的空隙。
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel) #再来一个闭操作
cv_show('thresh',thresh)


"""
计算图像的轮廓。cv2.findContours函数用来寻找二值图像中的轮廓。
这里使用的是cv2.RETR_EXTERNAL模式,表示只查找最外层的轮廓;cv2.CHAIN_APPROX_SIMPLE表示轮廓的存储方式,这种方式会存储轮廓的转折点,从而节省内存空间。
thresh.copy()是为了保护原图,因为findContours函数会修改输入的图像。
"""
threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = threshCnts
# 在原图上画出找到的轮廓。
# cv2.drawContours函数用来在图像上画出轮廓,-1表示画出所有轮廓,(0,0,255)是轮廓的颜色,这里是红色,3是轮廓的宽度。
cur_img = image.copy()
cv2.drawContours(cur_img,cnts,-1,(0,0,255),3) 
cv_show('img',cur_img)


# 下面这段代码的主要目的是从所有找到的轮廓中筛选出数字的轮廓,并将这些轮廓按照从左到右的顺序排序。
locs = [] # 初始化一个空列表 locs,用于存储选出来的轮廓。
# 遍历找到的所有轮廓
for (i, c) in enumerate(cnts):
	# 对于每个轮廓,先计算其外接矩形,得到矩形的坐标 (x, y) 和宽高 (w, h)
	(x, y, w, h) = cv2.boundingRect(c)

	"""
	计算矩形的长宽比(宽度除以高度)。如果一个轮廓的外接矩形的长宽比在一定范围内(比如这里的2.5到4.0),
	并且宽度和高度也在一定范围内(比如这里的宽度40到55,高度10到20),就认为这个轮廓可能是一个数字的轮廓,将其保存到 locs 中。
	"""
	ar = w / float(h)
	# 选择合适的区域,根据实际任务来,这里的基本都是四个数字一组
	if ar > 2.5 and ar < 4.0:
		if (w > 40 and w < 55) and (h > 10 and h < 20):
			# 符合的留下来
			locs.append((x, y, w, h))
			# 展示此时的结果
			clone = image.copy()
			cv2.rectangle(clone, (x, y), (x + w, y + h), (0, 255, 0), 2)
			cv_show("Selection", clone)

# 对 locs 中的轮廓按照 x 坐标(即从左到右)进行排序。
locs = sorted(locs, key=lambda x:x[0]) # locs是一个包含4个元素的列表
# 展示排序后的结果
for (i, (gX, gY, gW, gH)) in enumerate(locs):
	clone = image.copy()
	cv2.rectangle(clone, (gX, gY), (gX + gW, gY + gH), (0, 255, 0), 2)
	cv_show("Sorted", clone)



# 这段代码的目的是遍历存储的符合条件的轮廓(即信用卡上的数字组),对每一组数字进行处理以识别出其中的数字,并将识别的数字显示在图像上。
output = []
# 遍历 locs 列表,它包含了一系列的轮廓(或者说是数字组)。每个轮廓都有自己的坐标 (gX, gY) 和尺寸 (gW, gH)
for (i, (gX, gY, gW, gH)) in enumerate(locs):
	# 初始化一个空列表 groupOutput,用于保存当前轮廓(数字组)内识别出的数字
	groupOutput = []

	# 这一行是从灰度图像中切出当前轮廓(数字组)的部分。稍微比轮廓大一些,是为了尽量避免切割到数字。
	group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5]
	cv_show('group',group)
	# 对切出的图像进行二值化处理。二值化可以使得后续的轮廓检测操作更准确。
	group = cv2.threshold(group, 0, 255,
		cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
	cv_show('group',group)

	# 在二值化后的图像中寻找轮廓,这个轮廓就对应于信用卡上的每一个数字。
	digitCnts, hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
	# 将找到的轮廓(即数字)按照从左到右的顺序进行排序,以确保我们识别出的信用卡号是按照正确的顺序。
	digitCnts = contours.sort_contours(digitCnts,
		method="left-to-right")[0]

	# 遍历每一个数字的轮廓
	for c in digitCnts:
		# 找到当前数值的轮廓,resize成合适的的大小
		(x, y, w, h) = cv2.boundingRect(c)
		# 从数字组图像中切出当前数字的部分
		roi = group[y:y + h, x:x + w]
		# 将切出的数字图像的尺寸调整为57x88,这是为了和模板的尺寸一致,从而可以进行模板匹配。
		roi = cv2.resize(roi, (57, 88))
		cv_show('roi',roi)

		# 计算匹配得分
		scores = []
		# 遍历每一个数字模板
		for (digit, digitROI) in digits.items():
			# 将切出的数字图像和模板进行匹配,得到的结果是一个矩阵,每一个元素是对应位置上的匹配得分。
			result = cv2.matchTemplate(roi, digitROI,
				cv2.TM_CCOEFF)
			# 找到匹配得分矩阵中的最大值和最小值,以及它们的位置。score 是最大匹配得分
			(_, score, _, _) = cv2.minMaxLoc(result)
			scores.append(score) # 将当前模板的匹配得分添加到得分列表中

		# 在所有模板的匹配得分中找出最大的那个,最大得分对应的数字就是识别出来的数字。将识别出来的数字添加到当前数字组的输出列表中。
		groupOutput.append(str(np.argmax(scores)))

	"""
	这两行代码的主要目的是在原始图像上标记出识别的数字,并且显示识别结果。
	
	1. cv2.rectangle(image, (gX - 5, gY - 5), (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1):
	这行代码用于在原始图像上画出一个矩形,表示每一组的数字区域。cv2.rectangle()函数的参数是:图像、左上角坐标、右下角坐标、颜色和线条宽度。
	(gX - 5, gY - 5) 和 (gX + gW + 5, gY + gH + 5) 分别是矩形的左上角和右下角坐标,
	(0, 0, 255) 是矩形的颜色(这里是红色,因为在OpenCV中,颜色是以BGR而非RGB表示的),1 是线条的宽度。
	
	2. cv2.putText(image, "".join(groupOutput), (gX, gY - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2): 
	这行代码是将识别的数字添加到图像上。cv2.putText()函数的参数是:图像、文本、位置、字体、字体大小、颜色和线条宽度。
	"".join(groupOutput) 是要添加的文本,它是将每一组识别的数字拼接成一个字符串;(gX, gY - 15) 是文本的位置,这里选择的是每一组数字的左上角稍微向上一点的位置;
	cv2.FONT_HERSHEY_SIMPLEX 是字体;0.65 是字体的大小;(0, 0, 255) 是字体的颜色(这里选择的也是红色);2 是线条的宽度。
	"""
	cv2.rectangle(image, (gX - 5, gY - 5),
		(gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)
	cv2.putText(image, "".join(groupOutput), (gX, gY - 15),
		cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)

	# 将识别出来的数字添加到最终的输出列表中
	output.extend(groupOutput)

# 打印出识别出来的信用卡类型和信用卡号。这里 FIRST_NUMBER 是一个字典,它将信用卡号的第一位数字映射到对应的信用卡类型。
print("Credit Card Type: {}".format(FIRST_NUMBER[output[0]]))
print("Credit Card #: {}".format("".join(output)))
cv_show("Image", image) # 显示处理后的图像,可以看到识别出的信用卡号已经被画在了原图上。

myutils.py

import cv2

"""
sort_contours函数的作用是对轮廓和其外接矩形进行排序。

让我们一步一步地解读:

- zip(cnts, boundingBoxes)将轮廓列表cnts和外接矩形列表boundingBoxes合并成一个列表,其中每个元素都是一个由轮廓和其外接矩形组成的元组。

- sorted(zip(cnts, boundingBoxes), key=lambda b: b[1][i], reverse=reverse)使用Python的sorted函数对上述列表进行排序。
    - 排序的关键是key=lambda b: b[1][i],其中b是列表中的一个元素,也就是一个由轮廓和其外接矩形组成的元组,b[1]是外接矩形,b[1][i]是外接矩形的x或y坐标,取决于i的值。
    - 如果reverse=True,则对结果进行反向排序,即从大到小排序;如果reverse=False,则直接按照从小到大的顺序排序。

- zip(*sorted(zip(cnts, boundingBoxes), key=lambda b: b[1][i], reverse=reverse))使用zip函数和*操作符将排序后的列表转换回原来的形式,即分别是轮廓列表和外接矩形列表。

- (cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes), key=lambda b: b[1][i], reverse=reverse))将返回的轮廓列表和外接矩形列表分别赋值给cnts和boundingBoxes。

所以,这行代码的总体作用是按照x或y坐标对轮廓和其外接矩形进行排序,然后返回排序后的轮廓列表和外接矩形列表。

怕同学们忘记,补充一个点:
cv2.boundingRect()函数是一个计算轮廓外接矩形的函数,它的参数是一个轮廓。

该函数返回一个表示外接矩形的四元组,这四个值分别为(x, y, w, h)。

- x 和 y 表示外接矩形左上角点的坐标。
- w 和 h 分别表示外接矩形的宽度和高度。

"""
def sort_contours(cnts, method="left-to-right"):
    reverse = False
    i = 0

    if method == "right-to-left" or method == "bottom-to-top":
        reverse = True

    if method == "top-to-bottom" or method == "bottom-to-top":
        i = 1
    boundingBoxes = [cv2.boundingRect(c) for c in cnts] #用一个最小的矩形,把找到的形状包起来x,y,h,w
    (cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
                                        key=lambda b: b[1][i], reverse=reverse))

    return cnts, boundingBoxes



"""
resize函数用于调整图像的大小

下面这段代码定义了一个叫做resize的函数,这个函数接收一个图像和一个宽度或高度的值(或两者都有),并将这个图像缩放到指定的尺寸。

如果没有给出宽度和高度值,那么函数将返回原图。插值方法默认为cv2.INTER_AREA。
"""
def resize(image, width=None, height=None, inter=cv2.INTER_AREA):
    dim = None # 这里初始化了一个变量dim,它将在后续的代码中被用作储存图像新的尺寸
    (h, w) = image.shape[:2] # 这里从输入图像的形状(即尺寸)中提取出图像的高度(h)和宽度(w)
    if width is None and height is None: # 这一行代码检查了是否给出了新的宽度或高度值。如果没有给出,那么函数将直接返回原图
        return image

    # 如果没有指定新的宽度,那么我们就需要按照新的高度值来缩放图像。计算新的宽度值的方法是通过新的高度值与原高度的比例来计算新的宽度。
    if width is None:
        r = height / float(h)
        dim = (int(w * r), height)
    else: #  如果给出了新的宽度值,那么我们就需要按照新的宽度值来缩放图像。计算新的高度值的方法是通过新的宽度值与原宽度的比例来计算新的高度。
        r = width / float(w)
        dim = (width, int(h * r))
    """
    这段if-else代码的作用是在保持图像原有长宽比(即纵横比)的条件下,根据给出的新的宽度或高度来计算出新的图像尺寸。

    例子1:如果只给出了新的高度值 height(即 width 是 None),那么我们需要计算出新的宽度值,方法是:
    首先,我们计算出新的高度值与原高度 h 的比例 r = height / float(h)。
    然后,我们根据这个比例来计算新的宽度值 w * r,并将其转化为整数(因为像素值必须是整数)。
    最后,我们得到新的图像尺寸 dim = (int(w * r), height)。
    
    例子2:如果给出了新的宽度值 width,那么我们需要计算出新的高度值,方法是:
    首先,我们计算出新的宽度值与原宽度 w 的比例 r = width / float(w)。
    然后,我们根据这个比例来计算新的高度值 h * r,并将其转化为整数。
    最后,我们得到新的图像尺寸 dim = (width, int(h * r))。
    这样做的好处是可以保证图像在缩放过程中不会发生扭曲,也就是保持了图像的原有长宽比。
    """

    # 调用cv2.resize函数,将图像缩放到新的尺寸
    resized = cv2.resize(image, dim, interpolation=inter)
    """
    cv2.resize()是OpenCV库中的一个函数,用于调整图像的大小。

    该函数接收三个参数:
    
    - 第一个参数 image:需要调整大小的原始图像。
    - 第二个参数 dim:一个包含两个元素的元组,表示新的图像大小。这个大小是你要调整到的目标大小。
    - 第三个参数 interpolation:插值方法,也就是当我们调整图像大小时,如何计算新的像素值。 cv2.INTER_AREA 是一种插值方法,适合于图像缩小。OpenCV还提供了其他插值方法,如 cv2.INTER_LINEAR(线性插值,也是默认方法)、cv2.INTER_CUBIC(立方插值)等,这些方法在图像放大时可能会有较好的效果。
    
    函数的返回值 resized 就是调整大小后的新图像。这个新图像的大小就是 dim 所指定的大小。
    
    举个例子,如果你有一个大小为1000x1000的图像,你希望将它缩小到500x500,那么你可以这样调用这个函数:
    
    resized_image = cv2.resize(original_image, (500, 500), interpolation=cv2.INTER_AREA)
    
    在这个例子中,resized_image 就是大小为500x500的新图像。
    """

    return resized # 返回缩放后的图像

到了这里,关于OpenCV之信用卡识别实战的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 机器学习:基于XGBoost对信用卡欺诈行为的识别

    作者:i阿极 作者简介:Python领域新星作者、多项比赛获奖者:博主个人首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞👍收藏📁评论📒+关注哦!👍👍👍 📜📜📜如果有小伙伴需要数据集和学习交流,文章下方有交流学习区!一起学习进步!💪 大家好,我

    2024年02月08日
    浏览(71)
  • 机器学习:基于AdaBoost算法模型对信用卡是否违约进行识别

    作者:i阿极 作者简介:数据分析领域优质创作者、多项比赛获奖者:博主个人首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞👍收藏📁评论📒+关注哦!👍👍👍 📜📜📜如果有小伙伴需要数据集和学习交流,文章下方有交流学习区!一起学习进步!💪 大家

    2024年02月08日
    浏览(52)
  • 机器学习:基于AdaBoost算法对信用卡精准营销建立模型(附案例实战)

    作者:i阿极 作者简介:Python领域新星作者、多项比赛获奖者:博主个人首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞👍收藏📁评论📒+关注哦!👍👍👍 📜📜📜如果有小伙伴需要数据集和学习交流,文章下方有交流学习区!一起学习进步!💪 订阅专栏案

    2023年04月09日
    浏览(50)
  • 【Python机器学习】SVM解决非线性问题和信用卡欺诈检测实战(附源码和数据集)

    需要全部源码和数据集请点赞关注收藏后评论区留言私信~~~ 支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的 间隔最大的线性分类器 ,间隔最大使它有别于感知机;SVM还包括 核技巧 ,这使它成为实质上的非线性分类器。SVM的的学

    2024年02月06日
    浏览(56)
  • 数据挖掘实战(2):信用卡诈骗分析

    ⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者: 秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据开发、数据分析等。 🐴欢迎小伙伴们 点赞👍🏻、收藏

    2024年02月07日
    浏览(58)
  • 信用卡 3D 认证是怎么回事

    信用卡分为: 3D 和非 3D。 3D(3D: 3 domain)信用卡(10%, 集中在东南亚地区)); 非 3D(90%, 集中在欧美地区) 1.1.1. 什么是 3D 信用卡 卡组织为了保证交易的安全性为信用卡添加了密码验证。不同的卡组织为这服务的叫法都不相同: Visa: verified by visa service(VBV)。在 Mastercard: MasterCard secure cod

    2023年04月19日
    浏览(51)
  • 删除AWS绑定的信用卡账户

    前言 想使用aws的免费一年的ec2服务,所以必须先绑定信用卡,试了绑定储蓄卡还不行。绑定信用卡的时候只需要写卡号,卡片到期日期以及户头名即可。买上面的服务都不需要输入密码就可以购买。如果你用的免费服务,如果到期1年之后有其他费用,会悄无声息的扣款你的

    2024年02月12日
    浏览(63)
  • MATLAB朴素贝叶斯(德国信用卡案例)

    我们matlab建模课的案例 数据以及代码 链接:https://pan.baidu.com/s/18qpV2qsHzwbnOgZBMBHdGQ?pwd=r8g2  提取码:r8g2 参考书:MATLAB数学建模方法与实践(第三版)p63-p66 导入数据及分类 计算数据的x和y 例: 数据大小为1000x25 x = 1000 y =  25 最后一列为是否失约 原数据1代表失约 2代表未失约 例

    2024年02月06日
    浏览(113)
  • 能正常支付的的虚拟信用卡汇总

    OpenAi采用的是Stripe Checkout进行付款,理论上支持大多数卡种,包括Visa、万事达和银联等。然而,由于OpenAI在Stripe中限制了部分国家的银行卡支付,因此可能会出现一些支付问题。最近您尝试使用了不少卡种,包括实体卡、虚拟卡等,但都未能成功绑定支付。同时,也尝试了全

    2023年04月23日
    浏览(53)
  • 【银行测试】银行项目,信用卡业务测试+常问面试(三)

    银行测试-信用卡业务 1、信用卡额度如何测试? 正常测试场景: 在ATM取款,取款的金额≤信用卡额度/2(例如:信用卡额度为:2W,在ATM可成功取款10000); 在POS机上刷卡消费金额,单笔金额≤信用卡额度,交易成功; 消费的金额,超过信用卡正常额度(1-10%)交易成功(例

    2024年01月16日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包