Python 实现JPG图像中特殊点的识别的四种方法

Python中想要识别图片中的特点,可以使用基于像素值的方法、基于边缘检测的方法、基于模板匹配的方法或基于特征提取的方法,本文主要介绍五种方法及相关示例代码。

1、基于像素值的方法

遍历每个像素,检查它的RGB(或灰度)值是否与目标点的RGB(或灰度)值相同。如果相同,则将该像素的坐标记录下来。

代码如下,

from PIL import Image

img = Image.open('image.jpg')
width, height = img.size

# 目标点的RGB值
red = (255, 0, 0)
green = (0, 255, 0)

# 遍历每个像素,检查它的RGB值是否与目标点的RGB值相同
red_points = []
green_points = []
for y in range(height):
    for x in range(width):
        pixel = img.getpixel((x, y))
        if pixel == red:
            red_points.append((x, y))
        elif pixel == green:
            green_points.append((x, y))

print('Red points:', red_points)
print('Green points:', green_points)

2、基于边缘检测的方法

使用Canny等边缘检测算法,在图像中找到边缘,并在边缘上寻找像素值满足条件的点。

代码如下,

import cv2

img = cv2.imread('image.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 100, 200)

# 目标点的颜色值
red = (0, 0, 255)
green = (0, 255, 0)

# 在边缘上寻找满足条件的点
red_points = []
green_points = []
for y in range(edges.shape[0]):
    for x in range(edges.shape[1]):
        if tuple(img[y][x]) == red and edges[y][x] != 0:
            red_points.append((x, y))
        elif tuple(img[y][x]) == green and edges[y][x] != 0:
            green_points.append((x, y))

print('Red points:', red_points)
print('Green points:', green_points)

3、基于模板匹配的方法

使用Opencv库中模板匹配函数matchTemplate,将目标点当作模板,在图像中匹配出所有符合模板的位置。

代码如下,

import cv2

img = cv2.imread('image.jpg')
temp_red = cv2.imread('red.jpg')
temp_green = cv2.imread('green.jpg')

# 使用模板匹配函数,找到符合条件的位置
res_red = cv2.matchTemplate(img, temp_red, cv2.TM_CCORR_NORMED)
res_green = cv2.matchTemplate(img, temp_green, cv2.TM_CCORR_NORMED)
threshold = 0.8
loc_red = np.where(res_red >= threshold)
loc_green = np.where(res_green >= threshold)
red_points = list(zip(*loc_red[::-1]))
green_points = list(zip(*loc_green[::-1]))

print('Red points:', red_points)
print('Green points:', green_points)

4、基于特征提取的方法

使用Opencv库中的SURF、SIFT等特征提取算法,提取图像中的关键点,并比对这些关键点与目标点的特征向量,从而得到目标点的位置。

代码如下,

import cv2

img = cv2.imread('image.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
surf = cv2.xfeatures2d.SURF_create(400)
kp, des = surf.detectAndCompute(gray, None)

# 目标点的颜色值
red = (0, 0, 255)
green = (0, 255, 0)

# 比对关键点与目标点的特征向量,得到目标点的位置
matcher = cv2.DescriptorMatcher_create(cv2.DescriptorMatcher_FLANNBASED)
for i in range(len(kp)):
    if tuple(img[int(kp[i].pt[1])][int(kp[i].pt[0])]) == red:
        matches = matcher.match(des[i], des_red)
        if len(matches) > 0:
            print('Red point:', kp[i].pt)
    elif tuple(img[int(kp[i].pt[1])][int(kp[i].pt[0])]) == green:
        matches = matcher.match(des[i], des_green)
        if len(matches) > 0:
            print('Green point:', kp[i].pt)

5、实现JPG图像中特殊点的识别实例

已有一张jpg格式黑白图片,其中特殊点分别用红色、绿色、蓝色三种颜色标出,并输出三种颜色的坐标。

代码如下,

import cv2

# 读取图像并转换为灰度图像
img = cv2.imread('image.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 分离红色、绿色、蓝色部分
lower_red = (0, 0, 200)
upper_red = (50, 50, 255)
red_mask = cv2.inRange(img, lower_red, upper_red)

lower_green = (0, 150, 0)
upper_green = (50, 255, 50)
green_mask = cv2.inRange(img, lower_green, upper_green)

lower_blue = (200, 0, 0)
upper_blue = (255, 50, 50)
blue_mask = cv2.inRange(img, lower_blue, upper_blue)

# 找到各个颜色部分的轮廓并绘制在原图上
contours, _ = cv2.findContours(red_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0, 0, 255), 3)

contours, _ = cv2.findContours(green_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0, 255, 0), 3)

contours, _ = cv2.findContours(blue_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (255, 0, 0), 3)

# 计算每种颜色部分的质心坐标并输出结果
moments_red = cv2.moments(red_mask)
cx_red = int(moments_red['m10'] / moments_red['m00'])
cy_red = int(moments_red['m01'] / moments_red['m00'])
print('Red dot:', cx_red, cy_red)

moments_green = cv2.moments(green_mask)
cx_green = int(moments_green['m10'] / moments_green['m00'])
cy_green = int(moments_green['m01'] / moments_green['m00'])
print('Green dot:', cx_green, cy_green)

moments_blue = cv2.moments(blue_mask)
cx_blue = int(moments_blue['m10'] / moments_blue['m00'])
cy_blue = int(moments_blue['m01'] / moments_blue['m00'])
print('Blue dot:', cx_blue, cy_blue)

# 显示结果图像
cv2.imshow('result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

推荐阅读
cjavapy编程之路首页