-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
375 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,375 @@ | ||
--- | ||
title: 计算机视觉 - 1.数元素数目 | ||
date: 2024-03-18 09:44:08 +0800 | ||
categories: [Python, CV] | ||
tags: [Python, CV] # TAG names should always be lowercase | ||
--- | ||
|
||
# 计算机视觉1 - 数元素数目 | ||
|
||
## 0. 任务目标 | ||
|
||
1. 统计每幅图中各化学元素的数目; | ||
2. 统计AI和Fe元素、Fe和P元素、AI和P元素重叠的数目,并且以图像的形式展示出两两元素的重叠情况; | ||
3. 统计AI、Fe和P元素三者重叠的数目,并以图像的形式展示出三种元素重叠情况。 | ||
4. 无论原始图像中的化学元素是何种颜色,均可实现本目标。 | ||
|
||
## 1. 实现任务 | ||
|
||
计算机视觉常用的方法是使用OpenCV的库函数对图像进行处理。因此我们先利用 `cv2.imread()` 函数读入图像数据。本例子中,共拥有3张图片,分别是Al,Fe和P(即铝、铁、磷)三种化学元素。下面是三张照片的样子。 | ||
|
||
<img src="D:\Coder\Github Repos\StandardL.github.io\assets\img\posts\2024-03-18-计算机视觉1\Al.jpg" alt="Al" style="zoom:50%;" /> | ||
|
||
<img src="D:\Coder\Github Repos\StandardL.github.io\assets\img\posts\2024-03-18-计算机视觉1\Fe.jpg" alt="Fe" style="zoom:50%;" /> | ||
|
||
<img src="D:\Coder\Github Repos\StandardL.github.io\assets\img\posts\2024-03-18-计算机视觉1\P.jpg" alt="P" style="zoom:50%;" /> | ||
|
||
读取的代码如下: | ||
|
||
```python | ||
# Set paths | ||
al_path = os.path.join('image', 'Al.jpg') | ||
fe_path = os.path.join('image', 'Fe.jpg') | ||
p_path = os.path.join('image', 'P.jpg') | ||
|
||
# Read images | ||
al = cv2.imread(al_path) | ||
fe = cv2.imread(fe_path) | ||
p = cv2.imread(p_path) | ||
``` | ||
|
||
注意,这里的路径最好不要直接写死,而是用python os库中提供的 `os.path.join()` 函数进行拼接处理。该函数能够自行判断当前运行环境而选择路径的分隔符,无论是Linux还是Windows都不会出错。 | ||
|
||
--- | ||
|
||
读入图片后,我们发现图片中的左上角logo处和左下角的 50nm 标识都不是我们需要的东西,需要剔除。因此我们需要对输入图像进行预处理: | ||
|
||
- 为了去除左上角的logo,根据观察可以看到,logo读取进来的图像矩阵所在的行数均在74行及以内,因此我们处理的时候可以针对logo所在的行数进行删除。 | ||
|
||
- 为了去除左下角的 50nm 标识,我们需要识别出白色区域并去除。 | ||
|
||
为了实现上面的目标,我们先将图片从RGB色彩通道转换为HSV(HSB)色彩通道。OpenCV的库函数也提供了相应的转换。我们平常所见的图片绝大多数都是RGB通道,即利用Red(红)、Green(绿)、Blue(蓝)三种颜色及其浓度来表示一张彩色图片。在8Bit色深的RGB图像中,RGB三个通道的取值区间均为[0, 255]。而HSV色彩通道是利用Hue(色调)、Saturation(饱和度)、Value(明度)三值来表示颜色。不同于RGB图像,HSV图像是根据色调H来确定颜色的,而RGB图像一般需要通过三个值共同参与来表达一种颜色。 | ||
|
||
处理代码如下: | ||
|
||
```python | ||
# RGB TO HSV | ||
def rgb2hsv(img): | ||
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) | ||
# split H, S, V | ||
h, s, v = cv2.split(hsv_img) | ||
return [h, s, v] | ||
``` | ||
|
||
显示HSV图像三通道的代码如下: | ||
|
||
```python | ||
def show_hsv_image(imgs: list): | ||
cv2.imshow('H', imgs[0]) | ||
cv2.imshow('S', imgs[1]) | ||
cv2.imshow('V', imgs[2]) | ||
cv2.waitKey(0) | ||
cv2.destroyAllWindows() | ||
``` | ||
|
||
未经处理前,Al的分拆HSV通道后的图像如下: | ||
|
||
![Al的HSV图像](D:\Coder\Github Repos\StandardL.github.io\assets\img\posts\2024-03-18-计算机视觉1\Al的HSV图像.png) | ||
|
||
在HSV图像中,查询可知黑色点范围如下: | ||
|
||
- H: [0, 180] | ||
- S: [0, 255] | ||
- V: [0, 46] | ||
|
||
白色点范围如下: | ||
|
||
- H: [0, 180] | ||
- S: [0, 30] | ||
- V: [221, 255] | ||
|
||
logo区域的像素点较为明亮,因此可以直接利用位置和V的值进行判断去除。 | ||
|
||
图像预处理代码如下: | ||
|
||
```python | ||
def remove_light(split_img: list): | ||
h, s, v = split_img | ||
for i in range(h.shape[0]): | ||
for j in range(h.shape[1]): | ||
# Remove black points | ||
if 0 <= h[i, j] <= 180 and 0 <= v[i, j] <= 46: | ||
h[i, j] = 0 | ||
s[i, j] = 0 | ||
v[i, j] = 0 | ||
# Remove white points | ||
elif 0 <= h[i, j] <= 180 and 221 <= v[i, j] <= 255 and 0 <= s[i, j] <= 30: | ||
h[i, j] = 0 | ||
s[i, j] = 0 | ||
v[i, j] = 0 | ||
# Remove logo area | ||
if i <= 70 and 180 <= v[i, j] <= 255: | ||
h[i, j] = 0 | ||
s[i, j] = 0 | ||
v[i, j] = 0 | ||
|
||
return [h, s, v] | ||
``` | ||
|
||
--- | ||
|
||
统计元素量时,为了方便统计,我们把有颜色的像素点都统计为1个元素。而我们已在上一步去除了杂色点,因此这一步可以直接数图像V通道的点数进行统计。统计函数如下: | ||
|
||
```python | ||
# Counting | ||
def count_points(img: list): | ||
h, s, v = img | ||
counter = 0 | ||
for i in range(v.shape[0]): | ||
for j in range(v.shape[1]): | ||
if v[i, j] != 0: | ||
counter += 1 | ||
|
||
return counter | ||
``` | ||
|
||
--- | ||
|
||
统计重叠量时,依旧是利用上一步的思想进行统计,但是这时候我们需要两张图片的交集,即需要多加一个“与”的判断步骤。为了显示图片,我们还需要返回合并后的HSV矩阵。 | ||
|
||
```python | ||
def count2overlap(img1: list, img2: list): | ||
h1, s1, v1 = img1 | ||
h2, s2, v2 = img2 | ||
h0 = np.zeros(h1.shape, dtype=np.uint8) | ||
s0 = np.zeros(s1.shape, dtype=np.uint8) | ||
v0 = np.zeros(v1.shape, dtype=np.uint8) | ||
counter = 0 | ||
for i in range(v1.shape[0]): | ||
for j in range(v1.shape[1]): | ||
if v1[i, j] != 0 and v2[i, j] != 0: | ||
h0[i, j] = h1[i, j] + h2[i, j] | ||
s0[i, j] = s1[i, j] + s2[i, j] | ||
v0[i, j] = v1[i, j] + v2[i, j] | ||
counter += 1 | ||
|
||
return counter, [h0, s0, v0] | ||
``` | ||
|
||
三张图片的元素重叠量也是同理。 | ||
|
||
```python | ||
def count3overlap(img1: list, img2: list, img3: list): | ||
h1, s1, v1 = img1 | ||
h2, s2, v2 = img2 | ||
h3, s3, v3 = img3 | ||
h0 = np.zeros(h1.shape, dtype=np.uint8) | ||
s0 = np.zeros(s1.shape, dtype=np.uint8) | ||
v0 = np.zeros(v1.shape, dtype=np.uint8) | ||
counter = 0 | ||
for i in range(v1.shape[0]): | ||
for j in range(v1.shape[1]): | ||
if v1[i, j] != 0 and v2[i, j] != 0 and v3[i, j] != 0: | ||
h0[i, j] = h1[i, j] + h2[i, j] + h3[i, j] | ||
s0[i, j] = s1[i, j] + s2[i, j] + s3[i, j] | ||
v0[i, j] = v1[i, j] + v2[i, j] + v3[i, j] | ||
counter += 1 | ||
|
||
return counter, [h0, s0, v0] | ||
``` | ||
|
||
至此,我们本例子的目标基本完成。由于我们将重要的功能封装成函数且与具体颜色无关,因此无论原始图像中的化学元素是何种颜色,只需修改图像路径,均可实现本目标。 | ||
|
||
--- | ||
|
||
完整代码如下: | ||
|
||
```python | ||
import os.path | ||
import cv2 | ||
import numpy as np | ||
import matplotlib.pyplot as plt | ||
|
||
# Set paths | ||
al_path = os.path.join('image', 'Al.jpg') | ||
fe_path = os.path.join('image', 'Fe.jpg') | ||
p_path = os.path.join('image', 'P.jpg') | ||
|
||
# Read images | ||
al = cv2.imread(al_path) | ||
fe = cv2.imread(fe_path) | ||
p = cv2.imread(p_path) | ||
|
||
|
||
# RGB TO HSV | ||
def rgb2hsv(img): | ||
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) | ||
# split H, S, V | ||
h, s, v = cv2.split(hsv_img) | ||
return [h, s, v] | ||
|
||
|
||
# Plot image | ||
def show_image3(imgs: list): | ||
plt.figure(figsize=(15, 15)) | ||
for i, img in enumerate(imgs): | ||
plt.subplot(1, 3, i + 1) | ||
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) | ||
plt.axis('off') | ||
plt.show() | ||
|
||
|
||
# Plot HSV image | ||
def show_hsv_image(imgs: list): | ||
cv2.imshow('H', imgs[0]) | ||
cv2.imshow('S', imgs[1]) | ||
cv2.imshow('V', imgs[2]) | ||
cv2.waitKey(0) | ||
cv2.destroyAllWindows() | ||
|
||
|
||
# Remove black and white points and logo | ||
def remove_light(split_img: list): | ||
h, s, v = split_img | ||
for i in range(h.shape[0]): | ||
for j in range(h.shape[1]): | ||
# Remove black points | ||
if 0 <= h[i, j] <= 180 and 0 <= v[i, j] <= 46: | ||
h[i, j] = 0 | ||
s[i, j] = 0 | ||
v[i, j] = 0 | ||
# Remove white points | ||
elif 0 <= h[i, j] <= 180 and 221 <= v[i, j] <= 255 and 0 <= s[i, j] <= 30: | ||
h[i, j] = 0 | ||
s[i, j] = 0 | ||
v[i, j] = 0 | ||
# Remove logo area | ||
if i <= 70 and 180 <= v[i, j] <= 255: | ||
h[i, j] = 0 | ||
s[i, j] = 0 | ||
v[i, j] = 0 | ||
|
||
return [h, s, v] | ||
|
||
|
||
# Counting | ||
def count_points(img: list): | ||
h, s, v = img | ||
counter = 0 | ||
for i in range(v.shape[0]): | ||
for j in range(v.shape[1]): | ||
if v[i, j] != 0: | ||
counter += 1 | ||
|
||
return counter | ||
|
||
|
||
images = [al, fe, p] | ||
# show_image3(images) | ||
|
||
hsv_al = rgb2hsv(al) | ||
hsv_fe = rgb2hsv(fe) | ||
hsv_p = rgb2hsv(p) | ||
show_hsv_image(hsv_al) | ||
|
||
# pre-process | ||
processed_al = remove_light(hsv_al) | ||
processed_fe = remove_light(hsv_fe) | ||
processed_p = remove_light(hsv_p) | ||
|
||
# counting | ||
counter_al = count_points(processed_al) | ||
counter_fe = count_points(processed_fe) | ||
counter_p = count_points(processed_p) | ||
|
||
print("Al元素的点数:", counter_al) | ||
print("Fe元素的点数:", counter_fe) | ||
print("P元素的点数:", counter_p) | ||
|
||
|
||
# 求解重叠量,并将两者的重叠量画出来 | ||
def count2overlap(img1: list, img2: list): | ||
h1, s1, v1 = img1 | ||
h2, s2, v2 = img2 | ||
h0 = np.zeros(h1.shape, dtype=np.uint8) | ||
s0 = np.zeros(s1.shape, dtype=np.uint8) | ||
v0 = np.zeros(v1.shape, dtype=np.uint8) | ||
counter = 0 | ||
for i in range(v1.shape[0]): | ||
for j in range(v1.shape[1]): | ||
if v1[i, j] != 0 and v2[i, j] != 0: | ||
h0[i, j] = h1[i, j] + h2[i, j] | ||
s0[i, j] = s1[i, j] + s2[i, j] | ||
v0[i, j] = v1[i, j] + v2[i, j] | ||
counter += 1 | ||
|
||
return counter, [h0, s0, v0] | ||
|
||
|
||
# 求解三者的重叠量 | ||
def count3overlap(img1: list, img2: list, img3: list): | ||
h1, s1, v1 = img1 | ||
h2, s2, v2 = img2 | ||
h3, s3, v3 = img3 | ||
h0 = np.zeros(h1.shape, dtype=np.uint8) | ||
s0 = np.zeros(s1.shape, dtype=np.uint8) | ||
v0 = np.zeros(v1.shape, dtype=np.uint8) | ||
counter = 0 | ||
for i in range(v1.shape[0]): | ||
for j in range(v1.shape[1]): | ||
if v1[i, j] != 0 and v2[i, j] != 0 and v3[i, j] != 0: | ||
h0[i, j] = h1[i, j] + h2[i, j] + h3[i, j] | ||
s0[i, j] = s1[i, j] + s2[i, j] + s3[i, j] | ||
v0[i, j] = v1[i, j] + v2[i, j] + v3[i, j] | ||
counter += 1 | ||
|
||
return counter, [h0, s0, v0] | ||
|
||
|
||
# Get 2 overlap | ||
overlap_al_fe, overlap_img_af = count2overlap(processed_al, processed_fe) | ||
overlap_al_p, overlap_img_ap = count2overlap(processed_al, processed_p) | ||
overlap_fe_p, overlap_img_fp = count2overlap(processed_fe, processed_p) | ||
overlap_img_af = cv2.cvtColor(cv2.merge(overlap_img_af), cv2.COLOR_HSV2BGR) | ||
overlap_img_ap = cv2.cvtColor(cv2.merge(overlap_img_ap), cv2.COLOR_HSV2BGR) | ||
overlap_img_fp = cv2.cvtColor(cv2.merge(overlap_img_fp), cv2.COLOR_HSV2BGR) | ||
print("Al和Fe的重叠量:", overlap_al_fe) | ||
print("Al和P的重叠量:", overlap_al_p) | ||
print("Fe和P的重叠量:", overlap_fe_p) | ||
# show_image3([overlap_img_af, overlap_img_ap, overlap_img_fp]) | ||
|
||
# Get 3 overlap | ||
overlap_all, overlap_img_all = count3overlap(processed_al, processed_fe, processed_p) | ||
overlap_img_all = cv2.cvtColor(cv2.merge(overlap_img_all), cv2.COLOR_HSV2BGR) | ||
print("Al, Fe和P的重叠量:", overlap_all) | ||
# cv2.imshow('Overlay with Al, Fe and P elements', overlap_img_all) | ||
# cv2.waitKey(0) | ||
# cv2.destroyAllWindows() | ||
|
||
# Save images | ||
if not os.path.exists('image_out'): | ||
os.makedirs('image_out') | ||
cv2.imwrite(os.path.join('image_out', 'overlap_img_af.jpg'), overlap_img_af) | ||
cv2.imwrite(os.path.join('image_out', 'overlap_img_ap.jpg'), overlap_img_ap) | ||
cv2.imwrite(os.path.join('image_out', 'overlap_img_fp.jpg'), overlap_img_fp) | ||
cv2.imwrite(os.path.join('image_out', 'overlap_img_all.jpg'), overlap_img_all) | ||
|
||
``` | ||
|
||
最终的得到的重叠图片如下: | ||
|
||
- Al和Fe: | ||
|
||
<img src="D:\Coder\Github Repos\StandardL.github.io\assets\img\posts\2024-03-18-计算机视觉1\overlap_img_af.jpg" alt="overlap_img_af" style="zoom:50%;" /> | ||
|
||
- Al和P: | ||
|
||
<img src="D:\Coder\Github Repos\StandardL.github.io\assets\img\posts\2024-03-18-计算机视觉1\overlap_img_ap.jpg" alt="overlap_img_ap" style="zoom:50%;" /> | ||
|
||
- Fe和P: | ||
|
||
<img src="D:\Coder\Github Repos\StandardL.github.io\assets\img\posts\2024-03-18-计算机视觉1\overlap_img_fp.jpg" alt="overlap_img_fp" style="zoom:50%;" /> | ||
|
||
- 三者重叠: | ||
|
||
<img src="D:\Coder\Github Repos\StandardL.github.io\assets\img\posts\2024-03-18-计算机视觉1\overlap_img_all.jpg" alt="overlap_img_all" style="zoom:50%;" /> |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.