Loading...

我是基于CHatGPT实现的AI助手,在此网站上负责整理和概括文章

文章介绍了在低光照条件下开发的蠕变试验自动数值读取系统,主要利用Retinex算法对图像进行增强,同时使用霍夫变换检测圆形与直线位置。通过树莓派模块实现了对灯光的自动控制,并收集了光照数据进行分析。最终实现了对表盘位置和光照强度的记录,并通过分析数据来判断灯光状态。文章总结了实验进度与问题点,提出优化方案,最终实验完成度较高。

# 低照度图像增强计算机算法

为了解决在黑暗条件下无法识别蠕变实验指针问题。

[低光照图像增强算法汇总_低照度图像增强算法_Wanderer001 的博客 - CSDN 博客]

(https://blog.csdn.net/weixin_36670529/article/details/109058335)

# Retinex 算法(2023.3.1 日进度)

Retinex 算法 - CSDN 博客

传统图像处理 —— 图像增强 Retinex - 知乎 (zhihu.com)

img

核心:从 S 图像中估测 L 分量,并去除 L 分量,得到原始反射分量 R

# SSR (Single Scale Retinex) 单尺度 Retinex 算法

图像可以看做是入射图像和反射图像构成,入射光照射在反射物体上,通过反射物体的反射,形成反射光进入人眼。最后形成的图像可以如下公式表示:

S(x,y)=L(x,y)R(x,y)S(x,\, y)=L(x,\, y)\cdot R(x,\, y)

式中: I (x,y) 代表被观察或照相机接收到的图像信号;L (x,y) 代表环境光的照射分量 ;R (x,y) 表示携带图像细节信息的目标物体的反射分量 。

等式两边取对数得:

Log(R(x,y))=Log(I(x,y))Log(L(x,y))Log(R(x,y))=Log(I(x,y))-Log(L(x,y))

L (x,y) 由 I (x,y) 和一个高斯核的卷积来近似表示:

L(x,y)=I(x,y)G(x,y)L(x,y)=I(x,y)\ast G(x,y)

上式中 * 代表卷积,G (x,y) 代表高斯核。

最后,将 Log (R (x,y)) 量化为 0-255 范围的像素值:

R(x,y)=(ValueMin)/(MaxMin)255R(x,y)=(Value-Min)/(Max-Min)\ast 255

def SSR(img, size):
    res = img
    L_blur = cv2.GaussianBlur(res, (size, size))
    log_R = np.log(res + 0.001) - np.log(L_blur + 0.001)
    minvalue, maxvalue, minloc, maxloc = cv2.minMaxLoc(log_R)
    log_R = (log_R - minvalue) * 255.0 / (maxvalue - minvalue)
    dst = cv2.convertScaleAbs(log_R)
    dst = cv2.add(img, dst)
    return dst

# 多尺度 MSR (Multi-Scale Retinex) 多尺度 Retinex 算法

MSR 是在 SSR 基础上发展来的,优点是可以同时保持图像高保真度与对图像的动态范围进行压缩的同时,MSR 也可实现色彩增强、颜色恒常性、局部动态范围压缩、全局动态范围压缩,也可以用于 X 光图像增强。最为经典的就是 3 尺度的,即大、中、小。

对原始图像进行每个尺度的高斯滤波,得到模糊后的图像 Li (x,y), 其中小标 i 表示尺度数.

然后对每个尺度下进行累加计算:

Log(R(x,y))=Log(R(x,y))+Weight(i)(Log(I(x,y))Log(Li(x,y)))Log(R(x,y))=Log(R(x,y))+Weight(i)\ast (Log(I(x,y))-Log(Li(x,y)))

其中 Weight (i) 表示每个尺度对应的权重,要求各尺度权重之和必须为 1,经典的取值为等权重。

基本的计算原理:

RMSR=n=1Nwn(logIi(x,y)log(Ii(x,y)Gn(x,y)))R_{MSR}=\sum_{n=1}^{N}{w_{n}(logI_{i}(x,y)-log(I_{i}(x,y)\ast G_{n}(x,y)))}

上式中,I 为原始输入图像,G 是滤波函数,一般为高斯函数,N 为尺度的数量,W 为每个尺度的权重,一般都为 1/N, R 表示在对数域的图像的输出。

def MSR(img, scales):
    number = len(scales)
    res = img
    h, w = img.shape[:2]
    dst_R = np.zeros((h, w), dtype=np.float32)
    log_R = np.zeros((h, w), dtype=np.float32)
    for i in range(number):
        L_blur = cv2.GaussianBlur(res, (scales[i], scales[i]), 0)
        log_R += np.log(res + 0.001) - np.log(L_blur + 0.001)
    log_R = log_R / number
    cv2.normalize(log_R, dst_R, 0, 255, cv2.NORM_MINMAX)
    dst_R = cv2.convertScaleAbs(dst_R)
    dst = cv2.add(img, dst_R)
    return dst

# 霍夫变换圆形与直线检测

浅析霍夫变换检测直线和圆_python 霍夫圆检测找不到圆的原因 - CSDN 博客

% 霍夫变换理解 圆 2 维
close('all');
% 给出一个圆,圆心(1,1),半径 3
r = 3;
x = -2 : 0.5 : 4; % x 定义域
y = sqrt(r.^2 - (x-1).^2) + 1 + 0*(rand(1,length(x)) - 0.5); % 半个圆
% 图像空间上的圆
figure;
plot(x,y,'*'); % 实际点
hold on;
x0 = -2 : 0.01 : 4;
y0 = sqrt(r.^2 - (x0-1).^2) + 1;
plot(x0,y0); % 圆曲线
hold off;
axis equal; % 各个轴比例相同
xlabel('x');
ylabel('y');
% 参数空间
figure;
% set(gcf,'position',[100,100,500,500]);
theta = 0 : 0.01 : 2*pi;
for ir = 1 : 5
    for i = 1 : 1%length(x)
        a = x(i) - ir*cos(theta); % 极坐标
        b = y(i) - ir*sin(theta);
        plot(a,b); % 画圆
        hold on;
        plot(x(i),y(i), '*'); % 画圆心
    end
end
hold off;
grid on;
set(gca, 'xtick', -6:1:8);
axis equal;
xlabel('a');
ylabel('b');
print(gcf, '-djpeg', 'c2_2.jpg', '-r72');
% 霍夫变换 (Hough Transform)
% 直线
clc;clear;close('all');
% 测试点
x = [0,1,2,3,4];
y = x + 4 + 1*(rand(1,length(x))-0.5);
plot(x,y,'*');
hold on;
y1 = x + 4;
plot(x,y1);
xlabel('x');
ylabel('y');
print(gcf, '-djpeg', 'line1.jpg', '-r72');
% 笛卡尔坐标
figure;
legd = {};
k = 0:3;
for i = 1 : length(x)
    b = -x(i)*k + y(i);
    plot(k,b)
    hold on;
    legd = [legd, num2str(i)];
end
hold off;
% legend(legd);
grid on;
xlabel('k');
ylabel('b');
print(gcf, '-djpeg', 'line2.jpg', '-r72');
% 极坐标
figure;
theta = 0/180*pi : 0.1 : 180/180*pi;
for i = 1 : length(x)
    ruo = x(i)*cos(theta) + y(i)*sin(theta);
    plot(theta, ruo);
    hold on;
end
hold off;
grid on;
xlabel('\theta');
ylabel('\rho');
print(gcf, '-djpeg', 'line3.jpg', '-r72');
% 霍夫变换理解 圆 3 维
close('all');
% 给出一个圆,圆心(1,1),半径 3
r = 3;
x = -2 : 0.5 : 4; % x 定义域
y = sqrt(r.^2 - (x-1).^2) + 1 + 0*(rand(1,length(x)) - 0.5); % 半个圆
% 图像空间上的圆
figure;
plot(x,y,'*'); % 实际点
hold on;
x0 = -2 : 0.01 : 4;
y0 = sqrt(r.^2 - (x0-1).^2) + 1;
plot(x0,y0); % 圆曲线
hold off;
axis equal; % 各个轴比例相同
xlabel('x');
ylabel('y');
print(gcf, '-djpeg', 'c1.jpg', '-r72');
% 参数空间
% 3 维图画的很慢,可能有地方弄错了
figure;
% set(gcf,'position',[100,100,500,500]);
theta = 0 : 0.01 : 2*pi;
for ir = 1 : 2 : 5
    for i = 1 : 1%length(x)
        a = x(i) - ir*cos(theta); % 极坐标
        b = y(i) - ir*sin(theta);
        r = ir*ones(1,length(a));
        plot3(r,a,b,'b'); % 画圆
        hold on;
        plot3(r,x(i),y(i), 'r*'); % 画圆心
    end
end
hold off;
grid on;
set(gca, 'xtick', -6:1:8);
% axis equal;
xlabel('r');
ylabel('a');
zlabel('b');
print(gcf, '-djpeg', 'c2.jpg', '-r72');

# 配置树莓派模块(MONOSTICK)

PAL の使用方法|MONO-WIRELESS.COM

image-20230622145453447

目前还未实现将数据提取出来,进行判定的程序。

通过传感器的数据与图像数值双重判断,来控制灯光的开关,能够更加智能。

image-20230724175435928

结果:收集了半个月的数据,其中分析出来在 Lux 大于 250 时,100% 符合室内灯打开状态,尽管有些灯可能不亮导致不能稳定在 300lux。所以整合判断。

# 试验整体预期:

  1. 寻找合适的高斯核,降低图片模糊程度。Y
  2. 搞懂 MSSR、MSRCP Y
  3. 尝试使用实验指针图像。Y
  4. 通过树莓派来控制灯光的开关 Y
  5. 不断拍摄照片读取摄像头的每个帧率来判断光照强度 Y
  6. 整合代码,实现树莓派的操作。Y
  7. 提前判断光照强度,在进行图像处理 Y
  8. 改进代码,提高运算速度 Y

# 研究进度:

  1. 在 vscode 配置 opencv(2023.3.2 日进度)

    win10 系统 VSCODE 配置 opencv_vscode 配置 opencv_scott198512 的博客 - CSDN 博客

  2. 在 pycharm 配置 opencv(2023.3.20)

    1. data 文件夹中的 test1.jpg

    2. 编辑代码将输出图片保存到本地,并且保存到包括日期的文件夹内以时间命名。

    3. 在 pyhton 中使用 opencv 的时候出现该问题,虽然不影响运行,但是 imshow 等函数不能自动补全以及提示错误等搞得很难受,所以不能坐视不理 ,最终我的解决方案如下:

      右键文件夹 venv ,如图,设为 Excluded,文件夹变成橘色,橘势大好,问题解决。

      个人情况问题是完美解决了,提示消失,可以自动补全等,但是不是很懂什么原理,希望有明白的大佬指点一下,谢谢!(换成 VScode 完美解决)

  3. 将图片输出到本地 output 文件夹内,并且按照日期时间分类(2023.3.21)

  4. 将圆圈图片以及指针图片输出到 HARI 文件夹内,并按照日期时间分类(2023.4.5)

  5. 将程序上传到 GitHub (2023.4.6)

  6. 利用霍夫变换代码检测出圆盘指针的位置(2023.4.8)

  7. 删除多余 MSRCP 代码(2023.4.10)

  8. 实现批量读取与输出(虽然没什么用)(2023.4.15)

  9. 整合代码,将所有图片一次性处理完毕并分别保存(2023.4.17)

  10. 测试实验图片,发现部分图片过亮,读取不出指针,需要进行图像强度判断(2023.4.18)

  11. 目前实验的进度与问题点整理(2023 年 6 月 12 日)

  12. 调试好了树莓派的无线模块,目前可以测量温度,湿度,和光照(2023 年 6 月 22 日)

  13. 报告会:

​ 先週は 5.29-6.4 のデータを収集しました。今の値 m は、画像をグレースケール画像に変換した後の、各画素点の閾値(現在は 128 に設定されている)からの平均偏差になります。 先週収集したデータは次の図1のようになります。10 時 46 分以降、学生が研究室に入り、実験室の照明がつき、窓を閉めから、m 値は 35 前後で安定になりました。

image-20230612171243166

​ 但し、5.30 日のデータを分析して、10:44 の時(図 2)、mの数値は 47.3858。10:46 の時(図 3)、mの数値は 39.6049、値は高ければ高いほど良いと思いますけど。10:44(値が高い方)の写真の中でダイヤルの針を認められません。逆に 10:46 の時、針を認められます。また、ダイヤルの鏡面反射によるものである可能性もあります。そして、今の画像輝度の判定アルゴリズムが問題があります、今新しい方法を探しています。

image-20230612171251299

问题点:

​ 目前整体判断灰度图像与阈值的平均偏离程度的时候,可能图像中会存在亮度很高的区域,整张图的范围内取平均值时,会让数值的 m 不能准确反应表盘的明暗程度。可能会存在整体 m 值偏高,但无法读取表盘或者整体 m 值偏低,仍然可以读取表盘的情况。

原因:

​ 图像中存在偏亮区域,影响整体的平均值。

解决方法:

​ 将数值 m 的判断区域缩小,仅在表盘区域判断,首先判断出表盘位置并记录,其次使用记录下来的数据确定表盘位置(以便在不能识别的情况下判断),记录并分析数值 m。

进步:

​ 编写了 detecdetected_circle.py 程序实现了对表盘位置以及大小的记录,并在以后的判定中,只要摄像机的位置不变,一直都可以截取表盘位置的光照强度并分析数值 m 的大小。

# 目前实验完成度

image-20231221162918095

image-20231221162942796

实验可以通过摄像头以及感光元件进行精度确认,并且自动开启或关闭灯光,目前来说,在没有新的元件加入的情况下,该实验已经结束。