当前位置: 首页 > news >正文

电子网站怎么做网站做收付款接口

电子网站怎么做,网站做收付款接口,wordpress教程哪本好,酷家乐必须先学cad吗1、傅里叶变换 霍夫变换 直线 角度 旋转2、边缘检测 霍夫变换 直线角度 旋转3、四点透视 角度 旋转4、检测矩形轮廓 角度 旋转 1.目的 实现类似全能扫面王的图像校正功能 2. 基于轮廓提取和透射变换 基于轮廓提取和透射变换的矫正算法更适用于车牌、身份证、人民…1、傅里叶变换 霍夫变换 直线 角度 旋转2、边缘检测 霍夫变换 直线角度 旋转3、四点透视 角度 旋转4、检测矩形轮廓 角度 旋转 1.目的 实现类似全能扫面王的图像校正功能 2. 基于轮廓提取和透射变换 基于轮廓提取和透射变换的矫正算法更适用于车牌、身份证、人民币、书本、 发票一类矩形形状而且边界明显的物体矫正。所校正的内容必须要有清晰的完整轮廓。 基本步骤 图片灰度化二值化/canny边缘检测等操作检测轮廓,并筛选出目标轮廓通过横纵比或面积去除干扰轮廓)获取图像顶点透视变换 代码 import cv2 import numpy as npdef contour_to_rect(contour):pts contour.reshape(4, 2)print(pts)rect np.zeros((4, 2), dtype float32)# top-left point has the smallest sum# bottom-right has the largest sums pts.sum(axis 1) # print(s)rect[0] pts[np.argmin(s)] # print(pts[np.argmin(s)])rect[2] pts[np.argmax(s)]# compute the difference between the points:# the top-right will have the minumum difference# the bottom-left will have the maximum differencediff np.diff(pts, axis 1)rect[1] pts[np.argmin(diff)]rect[3] pts[np.argmax(diff)]return rect# approximate the contour by a more primitive polygon shape def approximate_contour(contour):peri cv2.arcLength(contour, True)return cv2.approxPolyDP(contour, 0.032 * peri, True)# 获取顶点坐标 def get_receipt_contour(contours):# loop over the contoursfor c in contours:approx approximate_contour(c)# if our approximated contour has four points, we can assume it is receipts rectangleif len(approx) 4:return approxdef wrap_perspective(img, rect):# unpack rectangle points: top left, top right, bottom right, bottom left(tl, tr, br, bl) rect# compute the width of the new imagewidthA np.sqrt(((br[0] - bl[0]) ** 2) ((br[1] - bl[1]) ** 2))widthB np.sqrt(((tr[0] - tl[0]) ** 2) ((tr[1] - tl[1]) ** 2))# compute the height of the new imageheightA np.sqrt(((tr[0] - br[0]) ** 2) ((tr[1] - br[1]) ** 2))heightB np.sqrt(((tl[0] - bl[0]) ** 2) ((tl[1] - bl[1]) ** 2))# take the maximum of the width and height values to reach# our final dimensionsmaxWidth max(int(widthA), int(widthB))maxHeight max(int(heightA), int(heightB))# destination points which will be used to map the screen to a scanned viewdst np.array([[0, 0],[maxWidth - 1, 0],[maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], dtype float32)# calculate the perspective transform matrixM cv2.getPerspectiveTransform(rect, dst)# warp the perspective to grab the screenreturn cv2.warpPerspective(img, M, (maxWidth, maxHeight))if __name__ __main__:img cv2.imread(./images/1.png)gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 用高斯滤波处理原图像降噪blur cv2.GaussianBlur(gray, (5, 5), 0)#canny边缘检测仅针对这次的输入图片edged cv2.Canny(blur, 50, 150)contours, h cv2.findContours(edged.copy(), modecv2.RETR_EXTERNAL, methodcv2.CHAIN_APPROX_SIMPLE)# img_contours cv2.drawContours(img.copy(), contours, -1, (0, 0, 255), 3)largest_contours sorted(contours, keycv2.contourArea, reverseTrue)[:5]# img_largest_contours cv2.drawContours( img.copy(), largest_contours, -1, (0, 0, 255), 3)receipt_contour get_receipt_contour(largest_contours)# img_receipt_contour cv2.drawContours(img.copy(), [receipt_contour], -1, (0, 0, 255), 3)ori_img img.copy()for coor in contour_to_rect(receipt_contour):cv2.circle(ori_img, (int(coor[0]), int(coor[1])), 1, (0, 0, 255), 4)# 进行透视变换scanned wrap_perspective(img.copy(), contour_to_rect(receipt_contour))2.1 图像灰度化  gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blur cv2.GaussianBlur(gray, (5, 5), 0)如果有噪声可以加个高斯滤波 2.2 canny边缘检测 edged cv2.Canny(blur, 50, 150) 三个参数分别输入图像最小阈值最大阈值 下图中左为输出右为边缘检测结果。看起来效果还行 左为所有轮廓绘制右为面积前五的绘制。可以看到书中长方形的框并不在检测中这是因为在进行边缘检测时色差不大导致没检测出来后续使用闭运算处理将连断出填充完。 但是对于图像边框或者说前景与背景色差不大时很难检测出来如下图放在白色桌面的安装指南 2.3 检测轮廓,并筛选出目标轮廓通过横纵比或面积去除干扰轮廓)  contours, h cv2.findContours(edged.copy(), modecv2.RETR_EXTERNAL, methodcv2.CHAIN_APPROX_SIMPLE)   img_contours cv2.drawContours(img.copy(), contours, -1, (0, 0, 255), 3) 检测图像轮廓并绘制所有的轮廓 # approximate the contour by a more primitive polygon shape def approximate_contour(contour):     peri cv2.arcLength(contour, True)     return cv2.approxPolyDP(contour, 0.032 * peri, True) # 获取顶点坐标 def get_receipt_contour(contours):     # loop over the contours     for c in contours:         approx approximate_contour(c)         # if our approximated contour has four points, we can assume it is receipts rectangle         if len(approx) 4:             return approx 在这个实现中approximate_contour函数使用cv2.approxPolyDP来近似轮廓。cv2.approxPolyDP的第二个参数是精度参数它是一个距离值表示近似轮廓与原始轮廓之间的最大距离。这个值是原始轮廓周长的百分比通常设置为一个很小的值例如0.02。第三个参数True表示近似出的多边形是闭合的。 get_receipt_contour函数然后使用这个近似函数来寻找一个四边形的轮廓假设这个四边形是收据的形状。如果找到了一个有四个顶点的轮廓它就返回这个轮廓。如果没有找到函数将返回None。 请注意这个函数假设收据是一个四边形并且是轮廓列表中面积最大的四边形。在实际应用中可能需要根据收据的具体形状和图像中的其他元素来调整这个函数。 2.4 获取图像顶点             receipt_contour get_receipt_contour(largest_contours)     img_receipt_contour cv2.drawContours(img.copy(), [receipt_contour], -1, (0, 0, 255), 3) def contour_to_rect(contour):     pts contour.reshape(4, 2)     print(pts)     rect np.zeros((4, 2), dtype float32)     # top-left point has the smallest sum     # bottom-right has the largest sum     s pts.sum(axis 1) #     print(s)     rect[0] pts[np.argmin(s)] #     print(pts[np.argmin(s)])     rect[2] pts[np.argmax(s)]     # compute the difference between the points:     # the top-right will have the minumum difference     # the bottom-left will have the maximum difference     diff np.diff(pts, axis 1)     rect[1] pts[np.argmin(diff)]     rect[3] pts[np.argmax(diff)]     return rect 在您提供的contour_to_rect函数中目标是将以四个顶点形式给出的轮廓转换为一个矩形这个矩形以特定的顺序排列顶点通常是顺时针或逆时针方向从左上角开始。然而在您提供的代码中存在一些问题包括一个拼写错误和一个可能的逻辑错误。我将为您纠正这些问题并提供一个完整的函数该函数将返回一个按正确顺序排列顶点的矩形。 ori_img img.copy() for coor in contour_to_rect(receipt_contour): cv2.circle(ori_img, (int(coor[0]), int(coor[1])), 1, (0, 0, 255), 4)  将筛选的四个点在图像中标注 2.5 透视变换 scanned wrap_perspective(img.copy(), contour_to_rect(receipt_contour)) def wrap_perspective(img, rect):# unpack rectangle points: top left, top right, bottom right, bottom left(tl, tr, br, bl) rect# compute the width of the new imagewidthA np.sqrt(((br[0] - bl[0]) ** 2) ((br[1] - bl[1]) ** 2))widthB np.sqrt(((tr[0] - tl[0]) ** 2) ((tr[1] - tl[1]) ** 2))# compute the height of the new imageheightA np.sqrt(((tr[0] - br[0]) ** 2) ((tr[1] - br[1]) ** 2))heightB np.sqrt(((tl[0] - bl[0]) ** 2) ((tl[1] - bl[1]) ** 2))# take the maximum of the width and height values to reach# our final dimensionsmaxWidth max(int(widthA), int(widthB))maxHeight max(int(heightA), int(heightB))# destination points which will be used to map the screen to a scanned viewdst np.array([[0, 0],[maxWidth - 1, 0],[maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], dtype float32)# calculate the perspective transform matrixM cv2.getPerspectiveTransform(rect, dst)# warp the perspective to grab the screenreturn cv2.warpPerspective(img, M, (maxWidth, maxHeight))   您提供的wrap_perspective函数是用于执行透视变换的这种变换通常用于将图像中的四边形区域如收据、文档等转换为俯视图即“扫描”视图。这个函数接受两个参数要变换的图像img和一个表示四边形顶点的numpy数组rect。 以下是函数中每一步的解释 解包四边形顶点将四边形的顶点解包为tl左上角、tr右上角、br右下角和bl左下角。 计算新图像的宽度通过计算对角线br到bl和tr到tl的距离来得到新图像的潜在宽度。使用欧几里得距离公式sqrt((x2 - x1)^2 (y2 - y1)^2)。 计算新图像的高度同样通过计算对角线tr到br和tl到bl的距离来得到新图像的潜在高度。 确定最终尺寸通过取宽度 和高度的最大值来确保四边形在变换后不会被裁剪。 定义目标点创建一个目标点数组dst这些点定义了变换后的四边形的顶点位置。这些点将图像映射到一个矩形的“扫描”视图。 计算透视变换矩阵使用cv2.getPerspectiveTransform函数计算从原始四边形到目标矩形的透视变换矩阵M。 执行透视变换使用cv2.warpPerspective函数应用透视变换到图像img上得到变换后的图像。   3. 基于霍夫直线探测和仿射变换 基于霍夫直线探测的矫正算法更适用于文本类等无明显边界图像的矫正。图像画面必须要干净 算法步骤 用霍夫线变换探测出图像中的所有直线。计算出每条直线的倾斜角求他们的平均值。根据倾斜角旋转矫正。最后根据文本尺寸裁剪图片。 代码 import cv2 import numpy as npimg cv2.imread(./images/4.jpg) src img.copy() gray cv2.cvtColor(src, cv2.COLOR_RGB2GRAY); edged cv2.Canny(src, 50, 200, apertureSize3);# 第5个参数就是阈值阈值越大检测精度越高 plines cv2.HoughLines(edged, 1, np.pi / 180, 200); if plines is not None:plines plines.reshape(-1, 2)print(len(plines), lines detected)sum_theta 0.0for rho, theta in plines:# rho, theta line[0]a np.cos(theta)b np.sin(theta)x0 a * rhoy0 b * rhox1 int(x0 1000*(-b))y1 int(y0 1000*(a))x2 int(x0 - 1000*(-b))y2 int(y0 - 1000*(a))sum_theta theta# 绘制直线cv2.line(src, (x1, y1), (x2, y2), (0, 0, 255), 2)# 计算平均角度 average_theta sum_theta / len(plines) angle np.degrees(average_theta) - 90# 计算旋转中心 center (float(img.shape[1] / 2.0), float(img.shape[0] / 2.0)) # 计算对角线长度作为旋转后图像的尺寸 length int(np.sqrt(img.shape[0]**2 img.shape[1]**2)) # 计算旋转矩阵 M cv2.getRotationMatrix2D(center, angle, 1) # 进行仿射变换并填充背景色为白色 src_rotate cv2.warpAffine(img, M, (length, length), borderValue(255, 255, 255))3.1 图像预处理 在此不赘述根据实际情况来 3.2 霍夫线变换 # 第5个参数就是阈值阈值越大检测精度越高 plines cv2.HoughLines(edged, 1, np.pi / 180, 200); 在OpenCV中cv2.HoughLines函数用于检测图像中的直线。它使用霍夫变换Hough Transform来找到图像中直线的参数然后将这些参数转换为图像中的直线。 您提供的代码片段plines cv2.HoughLines(edged, 1, np.pi / 180, 200);是使用霍夫变换在经过Canny边缘检测的图像edged中检测直线的例子。 这里的参数解释如下 edged这是已经通过Canny边缘检测得到的图像。1这是霍夫变换中使用的rho极径参数。它定义了检测直线时的搜索范围。较大的值会使检测到的直线更加稀疏而较小的值则可能导致检测到的直线更加密集。np.pi / 180这是霍夫变换中使用的theta角度参数。它定义了检测直线时的角度范围。这里使用的是单位圆上的角度即0到π弧度。200这是霍夫变换中使用的阈值参数。它定义了直线检测的灵敏度。较大的值会使检测到的直线更加稀疏而较小的值则可能导致检测到的直线更加密集。 if plines is not None:     plines plines.reshape(-1, 2)     print(len(plines), lines detected) 在OpenCV中cv2.HoughLines函数返回一个包含检测到的直线的数组如果没有任何直线被检测到这个数组将为None。这种情况可能发生在以下几种情况下 图像噪声如果图像中的噪声非常强烈可能会导致无法检测到任何直线。 参数设置cv2.HoughLines函数的参数设置如阈值、角度范围等可能不适合当前图像。如果参数设置不当可能无法检测到任何直线。 图像内容如果图像中没有明显的直线结构例如在复杂的自然场景中可能会检测不到直线。 图像大小如果图像非常小可能没有足够的空间来检测直线。 图像分辨率如果图像的分辨率非常低可能会导致检测到的直线不够精确。 图像方向如果图像的方向与霍夫变换的搜索方向不匹配可能会检测不到直线。 在实际应用中您可能需要根据图像的具体内容和噪声水平来调整cv2.HoughLines函数的参数以提高检测直线的效果。 sum_theta 0.0     for rho, theta in plines:         # rho, theta line[0]         a np.cos(theta)         b np.sin(theta)         x0 a * rho         y0 b * rho         x1 int(x0 1000*(-b))         y1 int(y0 1000*(a))         x2 int(x0 - 1000*(-b))         y2 int(y0 - 1000*(a))         sum_theta theta         # 绘制直线         cv2.line(src, (x1, y1), (x2, y2), (0, 0, 255), 2) 在您提供的代码片段中您正在遍历通过霍夫变换检测到的直线并将这些直线绘制在原始图像src上。每个直线由两个点定义这两个点是根据极径rho和角度theta计算出来的。 代码中的关键步骤如下 遍历plines数组其中每个元素是一个包含两个值rho和theta的元组。rho是直线与原点之间的距离而theta是从x轴正向到直线方向的角度以弧度为单位。 对于每个元素您首先提取rho和theta值。 使用np.cos(theta)和np.sin(theta)计算直线斜率a和b。 使用a * rho和b * rho计算直线上的两个点的x和y坐标。这些坐标是通过将rho值乘以直线的方向向量由a和b定义得到的。 使用int(x0 1000*(-b))和int(y0 1000*(a))计算第一个点的坐标其中1000是一个常数用于确保坐标在图像范围内。 使用int(x0 - 1000*(-b))和int(y0 - 1000*(a))计算第二个点的坐标。 使用cv2.line函数在原始图像src上绘制从第一个点到第二个点的直线颜色为红色线宽为2。 将角度theta累加到变量sum_theta中。 经过自己的多次实验发现霍夫线变换的弧度转化为角度时是以Y轴正半轴为0°顺时针计算角度。并且在仿射变换进行旋转时如果给的是正数就会逆时针旋转如果给的是负数就会顺时针旋转  3.3 旋转角度和旋转中心 # 计算平均角度 average_theta sum_theta / len(plines) angle np.degrees(average_theta) - 90 在OpenCV中cv2.HoughLines函数返回的角度参数是以弧度为单位的。这个函数使用霍夫变换来检测图像中的直线而霍夫变换中使用的角度参数是弧度制的。 霍夫变换是一种在图像中检测直线的方法它将图像中的每个点转换为一个参数空间中的一个点其中参数空间是一个笛卡尔坐标系x轴和y轴分别对应于图像中的直线的斜率和截距。在霍夫变换中θ是直线的倾斜角以弧度为单位。 因此当您从cv2.HoughLines函数中获取θ值时这些值是以弧度为单位的。如果您需要将它们转换为角度可以使用NumPy的np.degrees函数来进行转换。 请注意弧度与度的转换关系是 1 弧度180​ /Π 度 # 计算旋转中心 center (float(img.shape[1] / 2.0), float(img.shape[0] / 2.0)) # 计算对角线长度作为旋转后图像的尺寸 length int(np.sqrt(img.shape[0]**2 img.shape[1]**2)) 3.4 旋转矩阵 # 计算旋转矩阵 M cv2.getRotationMatrix2D(center, angle, 1) 3.5 仿射变换 # 进行仿射变换并填充背景色为白色 src_rotate cv2.warpAffine(img, M, (length, length), borderValue(255, 255, 255)) 4. 基于最小外接矩形和仿射变换 有明显的单一外接矩形的图像最好是文本。 算法步骤 灰度化以及预处理二值化/边缘检测最小外接矩形旋转中心、旋转角度以及旋转矩阵仿射变换 代码 import numpy as np import cv2 as cvdef binary(img):graycv.cvtColor(img,cv.COLOR_BGR2GRAY)ret,binary cv.threshold(gray,0,255,cv.THRESH_BINARY_INV|cv.THRESH_OTSU)return binarydef Transformation(img,src):coordsnp.column_stack(np.where(img0))print(coords)print(coords.shape)angle cv.minAreaRect(coords)[-1] #最小外接矩形print(angle)if angle-45:angle -(90angle)else:angle-anglecenter (w//2,h//2)M cv.getRotationMatrix2D(center,angle,1.0) #传入中心和角度 得到旋转矩形rotated cv.warpAffine(src,M,(w,h),flagscv.INTER_CUBIC,borderModecv.BORDER_REPLICATE)cv.putText(rotated,Angle:{:.2f} degrees.format(angle),(10,30),cv.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)#绘制文字cv.imshow(Rotated,rotated)src cv.imread(imageTextR.png) (h,w)src.shape[:2] graycv.cvtColor(src,cv.COLOR_BGR2GRAY) binarybinary(src) Transformation(binary,src) cv.imshow(src,src) cv.imshow(binary,binary) cv.waitKey(0) 4.1 灰度化以及预处理 不多赘述 4.2 二值化 ret,binary cv.threshold(gray,0,255,cv.THRESH_BINARY_INV|cv.THRESH_OTSU) 在OpenCV中cv2.threshold函数用于将图像转换为二值图像。您提供的代码片段ret, binary cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)是使用cv2.threshold函数对灰度图像gray进行阈值处理以创建一个二值图像binary。 这里的参数解释如下 gray这是您要进行阈值处理的灰度图像。0这是阈值处理的下限值。所有小于这个值的像素将被设置为0通常是黑色。255这是阈值处理的上限值。所有大于这个值的像素将被设置为255通常是白色。cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU这是阈值处理的方法。cv2.THRESH_BINARY_INV表示使用二值反转阈值即小于阈值的像素将被设置为255白色大于阈值的像素将被设置为0黑色。cv2.THRESH_OTSU表示使用Otsu’s方法来自动选择阈值。 Otsu’s方法是一种自动选择阈值的方法它通过最大化类间方差来选择最佳阈值。这种方法通常用于图像分割以区分前景和背景。 4.3 最小外接矩形  首先获取所有非零坐标元素 coordsnp.column_stack(np.where(binary0)) 在您提供的代码片段中coords np.column_stack(np.where(binary 0)) 是一个用于获取二值图像中所有非零像素位置的坐标的方法。具体步骤如下 创建二值图像首先您使用cv2.threshold函数创建了一个二值图像binary。在这个二值图像中值为0的像素代表背景而值为255的像素代表前景。 使用np.where获取非零像素位置np.where(binary 0) 是一个NumPy函数用于获取二值图像中所有非零像素的位置。这个函数返回一个包含所有非零像素坐标的元组其中第一个元素是x坐标第二个元素是y坐标。 将坐标堆叠为列向量使用np.column_stack函数将坐标堆叠为列向量。这个操作将创建一个二维数组其中每一行代表一个像素点的坐标。 然后寻找最小外接矩形  angle cv.minAreaRect(coords)[-1] 在OpenCV中cv2.minAreaRect函数用于找到图像中最小的外接矩形并返回该矩形的旋转角度。这个函数通常用于对象检测和图像识别任务中。 cv2.minAreaRect函数的参数是一个包含像素点的坐标数组这些点定义了一个多边形。函数返回的参数有三个1.矩形的中心点 2.矩形的长和宽 3.矩形的旋转角度 在您提供的代码片段中angle cv2.minAreaRect(coords)[-1]的目的是获取最小外接矩形的旋转角度。coords是一个包含像素点的坐标数组这些点定义了一个多边形即您之前通过np.column_stack(np.where(binary 0))获取的非零像素位置。 angle_p cv.minAreaRect(coords) box_points cv.boxPoints(angle_p) box_points np.int0(box_points) cv.circle(src, [146,284], 1, (0, 0, 255), 4) srca cv.drawContours(src, [box_points], -1, (0, 0, 255), 2) 》》》15.60267448425293 可以看到画出的外接矩形不能将文字全部包裹住其角度为15.6同样是以y轴正半轴为0°顺时针为度数。 4.4 中心角度矩阵 cv.getRotationMatrix2D(center, angle, scale) → M 参数说明center表示旋转中心坐标二元元组 (x0, y0)。angle表示旋转角度单位为角度逆时针为正数顺时针为负数。scale表示缩放因子。 4.5 仿射变换 需要说明的是不管是霍夫线变换还是最小外接矩形都是为了获取图像的一个倾斜角度。按上面画出的外接矩形来进行仿射变换来本不能完成校正但是因为文字与x轴正半轴夹角为15.5然后最小外接矩形的角度刚好是15.6经过angle-angle变换后输入到旋转矩阵的角度就为-15.5然后仿射变换的旋转就是正数就是逆时针旋转负数就是顺时针旋转所以将原图顺时针旋转后就刚好校正了。 参考 OpenCV实战之三 | 基于OpenCV实现图像校正
http://www.w-s-a.com/news/564642/

相关文章:

  • 网站开发组合淘宝网站开发选什么类目
  • 广东手机网站建设个人电脑做网站主机
  • 健身俱乐部网站开发文档建一个网站需要什么条件
  • 买的网站模板怎么做建设行政管理部门网站
  • 怎么让百度多收录网站关键词seo深圳
  • 陕西交通建设集团网站体检个人网站设计模板田田田田田田田田
  • ae模板网站推荐安徽建筑信息平台
  • 新网站建设代理商wordpress模板商店
  • 中国十大设计素材网站wordpress发布失败
  • 江西省建设监理网站网页制作与设计是什么
  • 在招聘网站做销售怎么样网址你懂我意思正能量不用下载ios
  • 高端企业网站定制公司企业网站2000元
  • 成都网站建设:河北省建设工程质量监督网站
  • 四川省建设厅官网信息查询平台北京seo关键词优化外包
  • 网站建设响应式是什么意思wordpress弹窗打开网页
  • 做美工需要参考的网站漳州做网站的公司
  • 用源码建设网站关于网站开发的自我评价
  • 网站设计师图片自助建站编辑器
  • 网站建设的常用技术有哪些深圳建筑工地招工
  • 做软装找图片的网站wordpress 替代
  • 制作网站的后台公众号做视频网站会封吗
  • 广西企业建站邯郸景区网站制作
  • 开发商城网站多少钱城厢区建设局网站
  • 网站外链多的危害天水市建设局网站
  • 网站接入商学交互设计网站
  • 目前最新的网站后台架构技术综述什么网站可以做名片
  • 成都建站长沙做网站美工的公司
  • 湖南省住房与城乡建设厅网站平顶山网站关键词优化
  • 购物网站前台功能模块汕头网站设计电话
  • 网站你懂我意思正能量免费wordpress菜单底部导航代码