红苹果的圆度、直径大小标定

function fruitImageProcessingGUI
    % 创建主窗口和控件
    mainFigure = figure('Units', 'normalized', 'Position', [0.3, 0.3, 0.4, 0.4]);
    instructionText = uicontrol('Style', 'text', 'String', '请点击按钮执行相应的图像处理步骤', ...
        'Units', 'normalized', 'Position', [0.1, 0.7, 0.8, 0.2], 'FontSize', 12);
    readImageBtn = uicontrol('Style', 'pushbutton', 'String', '读取图像', ...
        'Units', 'normalized', 'Position', [0.2, 0.4, 0.6, 0.1], 'FontSize', 12, ...
        'Callback', @readImageBtn_Callback);
    thresholdBtn = uicontrol('Style', 'pushbutton', 'String', '阈值化', ...
        'Units', 'normalized', 'Position', [0.2, 0.3, 0.6, 0.1], 'FontSize', 12, ...
        'Enable', 'off', 'Callback', @thresholdBtn_Callback);
    % 在这里继续添加其他按钮和控件
    
    % 存储GUI数据的结构体
    handles = struct();
    
    % 读取图像按钮的回调函数
    function readImageBtn_Callback(~, ~)
        % 读取图像
        rgb = imread('fruit.jpg');
        [m, n, d] = size(rgb);

        % 更新说明文本框
        set(instructionText, 'String', '图像已读取');
        
        % 将图像保存到GUI数据中,以便其他按钮功能使用
        handles.rgb = rgb;
        handles.m = m;
        handles.n = n;
        handles.d = d;
        
        % 启用下一个按钮
        set(thresholdBtn, 'Enable', 'on');
        
        % 更新GUI数据
        guidata(mainFigure, handles);
    end

    % 阈值化按钮的回调函数
    function thresholdBtn_Callback(~, ~)
        % 获取GUI数据中的图像和尺寸信息
        rgb = handles.rgb;
        m = handles.m;
        n = handles.n;
        d = handles.d;

        % 阈值设置
        level1 = [255 * 0.2, 255 * 0.3];

        % 转换数据类型,图像输出类型只能是uint型
        rgb = uint8(rgb);

        % 剔除r-g < level1(1), r-g < level1(2)的部分
        r = rgb;
        for i = 1:m
            for j = 1:n
                if (rgb(i, j, 1) - rgb(i, j, 2)) < level1(1) && (rgb(i, j, 1) - rgb(i, j, 3)) < level1(2)
                    r(i, j, 1) = 0;
                    r(i, j, 2) = 0;
                    r(i, j, 3) = 0;
                end
            end
        end

        % 更新说明文本框
        set(instructionText, 'String', '图像阈值化完成');

        % 在此处可以添加显示阈值化后的图像的代码,例如使用imshow函数显示r

        % 更新GUI数据
        handles.rgb = r;
        guidata(mainFigure, handles);
    end

    % 在这里继续添加其他按钮的回调函数

end
function imageSegmentationGUI()
    % 创建GUI窗口
    fig = figure('Name', '目标与背景的分割与提取', 'NumberTitle', 'off', 'Position', [200, 200, 900, 600]);

    % 创建UI组件
    btnSelectImage = uicontrol('Style', 'pushbutton', 'String', '选择图像', 'Position', [50, 500, 100, 30], 'Callback', @selectImage);
    btnMeanFilter = uicontrol('Style', 'pushbutton', 'String', '均值滤波', 'Position', [50, 450, 100, 30], 'Callback', @applyMeanFilter);
    btnThresholding = uicontrol('Style', 'pushbutton', 'String', '二值图像', 'Position', [50, 400, 100, 30], 'Callback', @applyThresholding);
    btnOpening = uicontrol('Style', 'pushbutton', 'String', '开启运算', 'Position', [50, 350, 100, 30], 'Callback', @applyOpening);
    btnClosing = uicontrol('Style', 'pushbutton', 'String', '闭合运算', 'Position', [50, 300, 100, 30], 'Callback', @applyClosing);
    btnEdgeDetection = uicontrol('Style', 'pushbutton', 'String', '提取边缘', 'Position', [50, 250, 100, 30], 'Callback', @applyEdgeDetection);
    btnShowResult = uicontrol('Style', 'pushbutton', 'String', '显示结果', 'Position', [50, 200, 100, 30], 'Callback', @showResult);
    btnSegmentation = uicontrol('Style', 'pushbutton', 'String', '分割图像', 'Position', [50, 150, 100, 30], 'Callback', @performSegmentation);
    btnExit = uicontrol('Style', 'pushbutton', 'String', '退出', 'Position', [50, 100, 100, 30], 'Callback', @exitGUI);
    

    axesHandle1 = axes('Parent', fig, 'Position', [0.3, 0.1, 0.6, 0.8]);

    % 全局变量
    rgb = [];
    r=[];
    grayImage = [];
    thresholdedImage = [];
    openedImage = [];
    closedImage = [];
    edgeImage = [];
    resultImage = [];

    % 图像处理函数
    function selectImage(~, ~)
        [fileName, pathName] = uigetfile({'*.jpg;*.png;*.bmp', '图像文件 (*.jpg, *.png, *.bmp)'}, '选择图像');

        if isequal(fileName, 0) || isequal(pathName, 0)
            return;
        end

        % 读取图像
        rgb = imread(fullfile(pathName, fileName));

        % 显示原图像
        imshow(rgb, 'Parent', axesHandle1);
    end

    function applyMeanFilter(~, ~)
        if isempty(rgb)
            errordlg('请先选择图像!', '错误');
            return;
        end

        % 均值滤波
        r2=rgb;
        grayImage = rgb2gray(r2);
        n = 3;
        template = ones(n) / (n * n);
        filteredImage = imfilter(double(grayImage), template, 'replicate');

        % 显示均值滤波后的图像
        imshow(filteredImage, 'Parent', axesHandle1);
    end

    function applyThresholding(~, ~)
        if isempty(grayImage)
            errordlg('请先进行均值滤波!', '错误');
            return;
        end

        % 二值图像
        threshold = graythresh(grayImage);
        thresholdedImage = imbinarize(grayImage, threshold);

        % 显示二值图像
        imshow(thresholdedImage, 'Parent', axesHandle1);
    end

    function applyOpening(~, ~)
        if isempty(thresholdedImage)
            errordlg('请先进行二值图像处理!', '错误');
            return;
        end

        % 开启运算
        se = strel('disk', 12);
        openedImage = imopen(thresholdedImage, se);

        % 显示开启运算后的图像
        imshow(openedImage, 'Parent', axesHandle1);
    end

    function applyClosing(~, ~)
        if isempty(openedImage)
            errordlg('请先进行开启运算!', '错误');
            return;
        end

        % 闭合运算
        se = strel('disk', 5);
        closedImage = imclose(openedImage, se);

        % 显示闭合运算后的图像
        imshow(closedImage, 'Parent', axesHandle1);
    end

    function applyEdgeDetection(~, ~)
        if isempty(closedImage)
            errordlg('请先进行闭合运算!', '错误');
            return;
        end

        % 提取边缘
        edgeImage = edge(closedImage, 'canny');

        % 显示边缘图像
        imshow(edgeImage, 'Parent', axesHandle1);
    end

    function showResult(~, ~)
        if isempty(edgeImage)
            errordlg('请先进行边缘提取!', '错误');
            return;
        end

        % 分割完成的图像
        resultImage = edgeImage; % 这里将边缘图像作为分割结果,您可以根据需要修改这部分代码

        % 显示分割结果
        imshow(resultImage, 'Parent', axesHandle1);
    end

    function performSegmentation(~, ~)
        if isempty(rgb)
            errordlg('请先选择图像!', '错误');
            return;
        end

        % 在这里执行分割任务
        % 根据您的代码进行相应的处理
        % ...

        % 显示分割结果
        resultImage = rgb; % 这里将原图像作为分割结果,您可以根据需要修改这部分代码

        % 显示分割结果
        imshow(resultImage, 'Parent', axesHandle1);
    end

    function exitGUI(~, ~)
        choice = questdlg('确定要退出吗?', '退出', '是', '取消', '取消');

        if strcmp(choice, '是')
            close(fig);
        end
    end
end

GUI界面设计如下
在这里插入图片描述
实现目标与背景的分割和提取

clear
clc
close all

h = 0.002; % 步长
x1 = 100;
x0 = 0:h:x1;
y0 = [2; 2; 2; 2]; % 初始条件,对应 x, y, z, w
% 不同的 c
c = 1:1:500;
N_c = length(c);
N_P = 300; % 假设穿过截面的共有 300 个点
BF = nan(N_c, N_P);
for k = 1:N_c
    c_k = c(k);
    disp(c_k)
    % 计算轨迹
    [y1, ~] = ODE_RK4_hyh(0:10*h:x1, 10*h, y0, [c_k, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]); % 先粗略的计算前几步,然后排除初始点的影响,舍弃不要
    [y1, ~] = ODE_RK4_hyh(x0 + x1, h, y1(:, end), [c_k, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]);
    % 计算 Poincare 平面
    Plane = [1; -1; 0; 0]; % x - y = 0 平面 (正方向)
    [tP_List, yP_List] = Solve_Poincare(x0, y1, Plane); % 计算 Poincare 平面
    % 对于混沌系统再加一条,如果系统稳定了,则将稳定点也记录在最终分岔图内:
    if isempty(tP_List) && abs(y1(1, end) - y1(2, end)) < 1e-2 % 如果最后 x 和 y 足够接近,则认为收敛了
        tP_List = x0(end - 1:end);
        yP_List = y1(:, end - 1:end);
    end
    % 储存 y 值作为待会分岔图的点
    N_P_temp = size(tP_List, 2);
    if N_P_temp > N_P
        BF(k, 1:N_P) = yP_List(2, 1:N_P);
    else
        BF(k, 1:N_P_temp) = yP_List(2, 1:N_P_temp);
    end
end

% 绘制分岔图
figure()
hold on
for k = 1:N_P
    c_k = c(k);
    plot(c_k * ones(1, N_P), BF(k, 1:N_P), ...
        'LineStyle', 'none', 'Marker', '.', 'MarkerFaceColor', 'k', 'MarkerEdgeColor', 'k', ...
        'MarkerSize', 1)
end
hold off

function [tP_List, yP_List] = Solve_Poincare(t, y, Plane)
    % 截面方程 z = 0
    % Plane = [0; 0; 1; 0]; % 一般情况下是个垂直某个轴的平面
    % 一般只记录从负到正穿越。如果想反向也记录,可以设置 Plane = -Plane.

    % 第二步,插值得到线与面的交点
    yP_List = [];
    tP_List = [];
    Dis = DistancePlane(y, Plane);
    N = size(y, 2);
    for k = 1:N - 1
        if Dis(k) <= 0 && Dis(k + 1) > 0
            t0 = t(k);
            t1 = t(k + 1);
            yP0 = y(:, k);
            yP1 = y(:, k + 1);
            Dis0 = Dis(k);
            Dis1 = Dis(k + 1);
            % 一维线性插值,求 Dis = 0 时的 t 和 y
            yP = yP0 + (yP1 - yP0) / (Dis1 - Dis0) * (0 - Dis0);
            tP = t0 + (t1 - t0) / (Dis1 - Dis0) * (0 - Dis0);
            % 储存
            yP_List = [yP_List, yP];
            tP_List = [tP_List, tP];
        end
    end
end

% 点到平面的距离
function Dis = DistancePlane(xk, Plane)
    % xk,坐标点,如果是 3 维坐标,大小就是 3*N 的矩阵。
    % Plane,平面,形如 Ax + By + Cz + D = 0 形式的平面。

    N = size(xk, 2); % 计算总共多少个点
    xk2 = [xk; ones(1, N)];
    Dis = dot(xk2, Plane * ones(1, N), 1) / norm(Plane(1:end - 1));
end

function [F, Output] = Fdydx(x, y, Input)
    % 形式为 Y' = F(x, Y) 的方程,参见数值分析求解常系数微分方程相关知识
    % 高次用列向量表示,F = [dy(1); dy(2)]; y(1) 为函数,y(2) 为函数导数
    % 给定混沌系统的微分方程
    a = Input(1);
    b = Input(2);
    c = Input(3);
    d = Input(4);
    e = Input(5);
    f = Input(6);
    g = Input(7);
    h = Input(8);
    
    dxdt = a * y(3) * y(2) + c * y(4) * cos(y(2));
    dydt = -y(1) * y(3) + b * y(2) + e * y(1) + f * y(2);
    dzdt = y(1) * y(2) - c * y(3) + f * y(3);
    dwdt = y(2) * y(3) - d * y(4) + g * y(1) * cos(y(2)) + h * y(2) * sin(y(3));

    F = [dxdt; dydt; dzdt; dwdt];
    Output = [];
end

function [y, Output] = ODE_RK4_hyh(x, h, y0, Input)
    % 4阶RK方法
    % h 间隔为常数的算法
    y = zeros(size(y0, 1), size(x, 2));
    y(:, 1) = y0;
    for ii = 1:length(x) - 1
        yn = y(:, ii);
        xn = x(ii);
        [K1, ~] = Fdydx(xn, yn, Input);
        [K2, ~] = Fdydx(xn + h / 2, yn + h / 2 * K1, Input);
        [K3, ~] = Fdydx(xn + h / 2, yn + h / 2 * K2, Input);
        [K4, ~] = Fdydx(xn + h, yn + h * K3, Input);
        y(:, ii + 1) = yn + h / 6 * (K1 + 2 * K2 + 2 * K3 + K4);
    end
    Output = [];
end

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述 使用matlab对图像进行去噪处理、对彩色图像 进行目标和背景分析,通过阈值法将图像进行分割,提取特征参数,并对圆度和直径进行标定。使用均值滤波等一系列方法实现了对苹果的分割提取以及特征参数的标定。但是本次设计存在不足之处,对于重叠区域的分割与提取暂未处理好。
[1]陈贝文,陈淦.水果分类识别与成熟度检测技术综述[J].计算机时代,2022(07):62-65.DOI:10.16644/j.cnki.cn33-1094/tp.2022.07.016.
[2]王运祥,马本学,贾艳婷等.采用夹持果梗方法的水果检测分级机设计[J].食品与机械,2015,31(05):107-110.DOI:10.13652/j.issn.1003-5788.2015.05.027.
[3]苗玉彬,王浙明,刘秦.水果轮廓特征提取的Zernike矩分水岭分割方法[J].农业工程学报,2013,29(01):158-163.
[4]应义斌.水果图像的背景分割和边缘检测技术研究[J].浙江大学学报(农业与生命科学版),2000(01):37-40.
[5]徐琳,吕宇玲,王晓娟.水果的分割算法研究[J].数字通信世界,2018(05):274-275.
[6]苗玉彬,王浙明,刘秦.水果轮廓特征提取的Zernike矩分水岭分割方法[J].农业工程学报,2013,29(01):158-163.

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值