==,equal

==:

1、比较的是操作符两端的操作数是否是同一个对象
2、两边的操作数必须是同一类型的(可以是父子类之间)才能编译通过。
3、比较的是地址,如果是具体的阿拉伯数字的比较,值相等则为TRUE,如:
int a=10 与 long b=10L 与 double c=10.0都是相同的(为true),因为他们都指向地址为10的堆

equals:
1、比较的是两个对象的内容是否一样

String s="abce"是一种非常特殊的形式,和new 有本质的区别。它是java中唯一不需要new 就可以产生对象的途径。以String s="abce";形式赋值在java中叫直接量,它是在常量池中而不是象new一样放在压缩堆中。这种形式的字符串,在JVM内部发生字符串拘留,即当声明这样的一个字符串后,JVM会在常量池中先查找有有没有一个值为"abcd"的对象,如果有,就会把它赋给当前引用.即原来那个引用和现在这个引用指点向了同一对象,如果没有,则在常量池中新创建一个"abcd",下一次如果有String s1 = "abcd";又会将s1指向"abcd"这个对象,即以这形式声明的字符串,只要值相等,任何多个引用都指向同一对象.
而String s = new String("abcd");和其它任何对象一样.每调用一次就产生一个对象,只要它们调用。

也可以这么理解: String str = "hello"; 先在内存中找是不是有"hello"这个对象,如果有,就让str指向那个"hello".如果内存里没有"hello",就创建一个新的对象保存"hello". String str=new String ("hello") 就是不管内存里是不是已经有"hello"这个对象,都新建一个对象保存"hello"

具体可以看下面的代码:

public class test1 {
    public static void main(String[] args) {
        String a = new String("ab"); // a 为一个引用
        String b = new String("ab"); // b为另一个引用,对象的内容一样
        String aa = "ab"; // 放在常量池中
        String bb = "ab"; // 从常量池中查找
        if (aa == bb) // true
            System.out.println("aa==bb");
        if (a == b) // false,非同一对象
            System.out.println("a==b");
        if (a.equals(b)) // true
            System.out.println("aEQb");
        if (42 == 42.0) { // true
            System.out.println("true");
        }
    }
}

 

转载于:https://www.cnblogs.com/ok-lanyan/archive/2012/11/22/2782337.html

function recognize_math_expression_2() % 创建主窗口 fig = figure(‘Name’, ‘鲁棒公式识别系统’, ‘NumberTitle’, ‘off’, … ‘Position’, [100, 100, 1200, 800], ‘MenuBar’, ‘none’, … ‘Color’, [0.95 0.95 0.95]); % 创建UI控件 uicontrol('Style', 'pushbutton', 'String', '上传图像', ... 'Position', [30, 750, 100, 30], 'Callback', @uploadImage, ... 'FontSize', 11, 'BackgroundColor', [0.3 0.6 0.9], 'ForegroundColor', 'white'); uicontrol('Style', 'pushbutton', 'String', '识别公式', ... 'Position', [150, 750, 100, 30], 'Callback', @recognizeFormula, ... 'FontSize', 11, 'BackgroundColor', [0.1 0.7 0.3], 'ForegroundColor', 'white'); uicontrol('Style', 'pushbutton', 'String', '清除结果', ... 'Position', [270, 750, 100, 30], 'Callback', @clearResults, ... 'FontSize', 11, 'BackgroundColor', [0.9 0.5 0.1], 'ForegroundColor', 'white'); % 创建图像显示区域 ax_original = axes('Parent', fig, 'Position', [0.05, 0.5, 0.4, 0.35]); title(ax_original, '原始图像'); axis(ax_original, 'off'); ax_processed = axes('Parent', fig, 'Position', [0.55, 0.5, 0.4, 0.35]); title(ax_processed, '处理图像'); axis(ax_processed, 'off'); ax_equal = axes('Parent', fig, 'Position', [0.05, 0.1, 0.4, 0.35]); title(ax_equal, '等号检测'); axis(ax_equal, 'off'); % 创建结果展示区域 result_panel = uipanel('Title', '识别结果', 'FontSize', 12, ... 'BackgroundColor', 'white', 'Position', [0.55, 0.1, 0.4, 0.35]); uicontrol('Parent', result_panel, 'Style', 'text', 'String', '识别公式:', ... 'Position', [20, 200, 80, 20], 'FontSize', 11, 'HorizontalAlignment', 'left'); formula_text = uicontrol('Parent', result_panel, 'Style', 'text', 'String', '', ... 'Position', [110, 200, 300, 20], 'FontSize', 11, 'HorizontalAlignment', 'left', ... 'BackgroundColor', 'white'); uicontrol('Parent', result_panel, 'Style', 'text', 'String', '计算结果:', ... 'Position', [20, 170, 80, 20], 'FontSize', 11, 'HorizontalAlignment', 'left'); calc_text = uicontrol('Parent', result_panel, 'Style', 'text', 'String', '', ... 'Position', [110, 170, 300, 20], 'FontSize', 11, 'HorizontalAlignment', 'left', ... 'BackgroundColor', 'white'); uicontrol('Parent', result_panel, 'Style', 'text', 'String', '用户答案:', ... 'Position', [20, 140, 80, 20], 'FontSize', 11, 'HorizontalAlignment', 'left'); answer_text = uicontrol('Parent', result_panel, 'Style', 'text', 'String', '', ... 'Position', [110, 140, 300, 20], 'FontSize', 11, 'HorizontalAlignment', 'left', ... 'BackgroundColor', 'white'); uicontrol('Parent', result_panel, 'Style', 'text', 'String', '验证结果:', ... 'Position', [20, 110, 80, 20], 'FontSize', 11, 'HorizontalAlignment', 'left'); result_text = uicontrol('Parent', result_panel, 'Style', 'text', 'String', '', ... 'Position', [110, 110, 300, 20], 'FontSize', 11, 'HorizontalAlignment', 'left', ... 'BackgroundColor', 'white'); % 等号检测日志 equal_log = uicontrol('Parent', result_panel, 'Style', 'listbox', ... 'String', {}, 'Position', [20, 30, 360, 70], 'FontSize', 10, ... 'BackgroundColor', 'white'); % 存储GUI句柄 handles = struct(); handles.ax_original = ax_original; handles.ax_processed = ax_processed; handles.ax_equal = ax_equal; handles.formula_text = formula_text; handles.calc_text = calc_text; handles.answer_text = answer_text; handles.result_text = result_text; handles.equal_log = equal_log; handles.current_image = []; handles.binary_image = []; handles.region_stats = []; handles.region_bboxes = []; handles.equal_sign_index = []; handles.ocr_results = []; guidata(fig, handles); % ======================== 回调函数 ======================== function uploadImage(~, ~) [filename, pathname] = uigetfile({'*.jpg;*.png;*.bmp', '图像文件 (*.jpg, *.png, *.bmp)'}, ... '选择公式图像'); if isequal(filename, 0) return; end img_path = fullfile(pathname, filename); img = imread(img_path); handles = guidata(fig); handles.current_image = img; % 显示原始图像 axes(handles.ax_original); imshow(img); title('原始图像'); % 预处理图像 gray_img = im2gray(img); % 图像锐化 - 增强边缘 sharpened_img = imsharpen(gray_img, 'Radius', 1.5, 'Amount', 1.2, 'Threshold', 0.1); % 自适应二值化 binary_img = imbinarize(sharpened_img, 'adaptive', 'Sensitivity', 0.7); inverted_img = ~binary_img; handles.binary_image = inverted_img; % 显示处理图像 axes(handles.ax_processed); imshow(inverted_img); title('二值化图像'); % 重置结果 set(handles.formula_text, 'String', ''); set(handles.calc_text, 'String', ''); set(handles.answer_text, 'String', ''); set(handles.result_text, 'String', ''); set(handles.equal_log, 'String', {}); axes(handles.ax_equal); cla; title('等号检测'); guidata(fig, handles); end function recognizeFormula(~, ~) handles = guidata(fig); if isempty(handles.current_image) errordlg('请先上传图像', '错误'); return; end try inverted_img = handles.binary_image; [img_h, img_w] = size(inverted_img); % ================= 第一步:区域分割 ================= axes(handles.ax_processed); imshow(inverted_img); title('区域分割'); drawnow; % 区域分割 cc = bwconncomp(inverted_img); stats = regionprops(cc, 'BoundingBox', 'Area', 'Eccentricity', 'Orientation', 'Solidity','IsEqual'); % 过滤噪点 min_area = max(20, img_h*img_w*0.0005); % 动态最小面积 valid_idx = [stats.Area] > min_area; stats = stats(valid_idx); % 按水平位置排序 bboxes = vertcat(stats.BoundingBox); [~, order] = sort(bboxes(:,1)); bboxes = bboxes(order, :); stats = stats(order); % 存储区域信息 handles.region_stats = stats; handles.region_bboxes = bboxes; % 显示分割结果 imshow(inverted_img); hold on; for i = 1:size(bboxes,1) rectangle('Position', bboxes(i,:), 'EdgeColor', [0.8 0.2 0.2], 'LineWidth', 1); end hold off; title(sprintf('分割出 %d 个区域', length(stats))); drawnow; % ================= 第二步:垂直探索等号检测 ================= axes(handles.ax_equal); imshow(inverted_img); title('等号检测过程'); hold on; log_entries = {}; candidate_pairs = []; % 找出所有类似减号的区域 dash_like_indices = []; for i = 1:length(stats) bbox = bboxes(i,:); w = bbox(3); h = bbox(4); % 减号特征:高宽比大,离心率高 aspect_ratio = w / h; eccentricity = stats(i).Eccentricity; if aspect_ratio > 1.5 && eccentricity > 0.9 dash_like_indices = [dash_like_indices; i]; rectangle('Position', bbox, 'EdgeColor', [0 0.8 0.8], 'LineWidth', 1.5); text(bbox(1)+5, bbox(2)-10, sprintf('%d', i), ... 'Color', [0 0.5 0.5], 'FontSize', 10, 'FontWeight', 'bold','IsEqual',i); end end log_entries{end+1} = sprintf('找到 %d 个减号样区域', length(dash_like_indices)); % 垂直探索寻找等号对 for i = 1:length(dash_like_indices) idx1 = dash_like_indices(i); bbox1 = bboxes(idx1,:); center_x1 = bbox1(1) + bbox1(3)/2; center_y1 = bbox1(2) + bbox1(4)/2; % 在垂直方向探索 for j = 1:length(dash_like_indices) if i == j, continue; end % 跳过自身 idx2 = dash_like_indices(j); bbox2 = bboxes(idx2,:); center_x2 = bbox2(1) + bbox2(3)/2; center_y2 = bbox2(2) + bbox2(4)/2; % 检查垂直位置关系 vertical_gap = abs(center_y1 - center_y2); avg_height = (bbox1(4) + bbox2(4))/2; % 检查水平对齐 horizontal_diff = abs(center_x1 - center_x2); avg_width = (bbox1(3) + bbox2(3))/2; % 检查尺寸相似性 width_ratio = max(bbox1(3), bbox2(3)) / min(bbox1(3), bbox2(3)); height_ratio = max(bbox1(4), bbox2(4)) / min(bbox1(4), bbox2(4)); % 等号对条件: % 1. 垂直距离在合理范围(1-3倍平均高度) % 2. 水平位置对齐(中心偏差小于宽度的一半) % 3. 尺寸相似(宽高比小于1.5) if vertical_gap > 0.5*avg_height && vertical_gap < 5*avg_height && ... horizontal_diff < avg_width/2 && ... width_ratio < 2 && height_ratio < 2 % 检查是否已经配对 if ~isempty(candidate_pairs) && any(ismember([idx1, idx2], candidate_pairs(:))) continue; end % 标记候选对 candidate_pairs = [candidate_pairs; idx1, idx2]; % 绘制连接线 plot([center_x1, center_x2], [center_y1, center_y2], 'g-', 'LineWidth', 1.5); log_entry = sprintf('发现等号候选对: %d 和 %d (垂直距离: %.1f, 水平偏差: %.1f)', ... idx1, idx2, vertical_gap, horizontal_diff); log_entries{end+1} = log_entry; end end end % 处理等号候选对 equal_sign_index = []; if ~isempty(candidate_pairs) % 选择最可能的一对(水平对齐最好) [~, best_idx] = min(abs(candidate_pairs(:,1) - candidate_pairs(:,2))); best_pair = candidate_pairs(best_idx, :); % 计算合并后的边界框 bbox1 = bboxes(best_pair(1), :); bbox2 = bboxes(best_pair(2), :); min_x = min(bbox1(1), bbox2(1)); max_x = max(bbox1(1)+bbox1(3), bbox2(1)+bbox2(3)); min_y = min(bbox1(2), bbox2(2)); max_y = max(bbox1(2)+bbox1(4), bbox2(2)+bbox2(4)); equal_bbox = [min_x, min_y, max_x-min_x, max_y-min_y]; % 创建完整的等号区域属性结构体 equal_region = struct(... 'BoundingBox', equal_bbox, ... 'Area', equal_bbox(3)*equal_bbox(4), ... 'Eccentricity', 0.9, ... % 等号通常是细长的 'Orientation', 0, ... % 水平方向 'Solidity', 0.7); % 中等实心度 % === 关键修复:确保字段顺序一致 === if ~isempty(stats) equal_region = orderfields(equal_region, fieldnames(stats)); end % 标记等号区域 rectangle('Position', equal_bbox, 'EdgeColor', [0.2 0.8 0.2], 'LineWidth', 3); text(equal_bbox(1)+5, equal_bbox(2)-15, '等号', ... 'Color', [0 0.6 0], 'FontSize', 12, 'FontWeight', 'bold'); % 更新区域列表 - 移除原始的两个区域 remaining_indices = setdiff(1:size(bboxes,1), best_pair); bboxes = bboxes(remaining_indices, :); stats = stats(remaining_indices); % === 关键修复:安全连接结构体 === if isempty(stats) stats = equal_region; % 当没有剩余区域时 else % 确保列向量结构 if size(stats, 2) > 1 stats = stats'; end % 连接结构体 stats = [stats; equal_region]; end % 添加合并后的等号区域 bboxes = [bboxes; equal_bbox]; % stats = [stats; equal_region]; % 使用完整结构体 % 重新排序并记录原始位置 [~, order] = sort(bboxes(:,1)); original_positions = 1:size(bboxes,1); new_order_indices = original_positions(order); % 记录等号位置(在排序后的位置) equal_position_in_original = size(bboxes,1); % 等号添加在末尾 equal_sign_index = find(new_order_indices == equal_position_in_original); % 应用排序 bboxes = bboxes(order, :); stats = stats(order); log_entries{end+1} = sprintf('确定等号: 区域 %d 和 %d 合并为区域 %d', ... best_pair(1), best_pair(2), equal_sign_index); else log_entries{end+1} = ‘未找到有效的等号对’; equal_sign_index = []; end hold off; % 更新日志 set(handles.equal_log, 'String', log_entries); % 存储更新后的区域信息 handles.region_stats = stats; handles.region_bboxes = bboxes; handles.equal_sign_index = equal_sign_index; % ================= 第三步:字符识别 ================= ocr_results = cell(1, size(bboxes,1)); ocr_results = cell(1, length(stats)); for i = 1:length(stats) % 检查是否为等号区域 if isfield(stats(i), 'IsEqual') && stats(i).IsEqual ocr_results{i} = '='; continue; end bbox = stats(i).BoundingBox; bbox = bboxes(i,:); x = floor(bbox(1)); y = floor(bbox(2)); w = max(floor(bbox(3)), 1); h = max(floor(bbox(4)), 1); % 提取区域图像 region_img = inverted_img(max(1,y):min(img_h,y+h-1), max(1,x):min(img_w,x+w-1)); % 运算符特征检测 [is_operator, operator_type] = detectOperator(region_img); if is_operator ocr_results{i} = operator_type; else % OCR识别数字和字母 char_set = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; ocr_result = ocr(region_img, 'CharacterSet', char_set, 'TextLayout', 'Block'); if ~isempty(ocr_result.Text) char = strtrim(ocr_result.Text); % 数字校正 if strcmp(char, '7') || strcmp(char, '1') char = correctDigit(region_img, char); end ocr_results{i} = char; else ocr_results{i} = '?'; end end end % ================= 第四步:构建表达式 ================= % 分割表达式和答案 expr_str = ''; answer_str = ''; % 找到等号位置 eq_idx = []; for i = 1:length(stats) if isfield(stats(i), 'IsEqual') && stats(i).IsEqual eq_idx = i; break; end end % 如果没有找到等号,使用位置最中间的区域作为等号 if isempty(eq_idx) [~, eq_idx] = min(abs(1:length(stats) - length(stats)/2)); log_entries{end+1} = sprintf(‘未找到等号,使用区域 %d 作为等号’, eq_idx); set(handles.equal_log, ‘String’, log_entries); end for i = 1:length(ocr_results) if i < eq_idx expr_str = [expr_str ocr_results{i}]; elseif i > eq_idx answer_str = [answer_str ocr_results{i}]; end end % 特殊字符转换 expr_str = strrep(expr_str, 'x', '*'); expr_str = strrep(expr_str, 'X', '*'); expr_str = strrep(expr_str, '÷', '/'); expr_str = strrep(expr_str, ' ', ''); % 尝试转换为数值 try user_answer = str2double(answer_str); catch user_answer = NaN; end % 安全计算表达式 try correct_result = eval(expr_str); catch % 修正常见OCR错误 expr_str = strrep(expr_str, 'O', '0'); expr_str = strrep(expr_str, 'o', '0'); expr_str = strrep(expr_str, 'l', '1'); expr_str = strrep(expr_str, 'I', '1'); expr_str = strrep(expr_str, 's', '5'); correct_result = eval(expr_str); end % 验证结果 is_correct = abs(user_answer - correct_result) < 1e-6; % 更新结果展示 set(handles.formula_text, 'String', [expr_str '=' answer_str]); set(handles.calc_text, 'String', num2str(correct_result)); set(handles.answer_text, 'String', num2str(user_answer)); if is_correct set(handles.result_text, 'String', '✓ 答案正确', 'ForegroundColor', [0 0.6 0]); else set(handles.result_text, 'String', '✗ 答案错误', 'ForegroundColor', [0.8 0 0]); end % 显示最终识别结果 axes(handles.ax_processed); imshow(inverted_img); hold on; for i = 1:size(bboxes,1) % 等号区域用绿色标注 if ~isempty(equal_sign_index) && i == equal_sign_index rectangle('Position', bboxes(i,:), 'EdgeColor', [0.2 0.8 0.2], 'LineWidth', 2); text(bboxes(i,1)+5, bboxes(i,2)-10, '=', ... 'Color', [0 0.5 0], 'FontSize', 12, 'FontWeight', 'bold'); else % 运算符区域用不同颜色标注 if strcmp(ocr_results{i}, '+') rect_color = [0.8 0.2 0.8]; % 紫色 text_color = [0.6 0 0.6]; % 深紫色 elseif strcmp(ocr_results{i}, '-') rect_color = [0.8 0.5 0.2]; % 橙色 text_color = [0.6 0.3 0]; % 深橙色 else rect_color = [1 0 0]; % 红色 text_color = [0 0 1]; % 蓝色 end rectangle('Position', bboxes(i,:), 'EdgeColor', rect_color, 'LineWidth', 1.5); if ~isempty(ocr_results{i}) text(bboxes(i,1)+5, bboxes(i,2)-10, ocr_results{i}, ... 'Color', text_color, 'FontSize', 10, 'FontWeight', 'bold'); end end end hold off; title('最终识别结果'); % 保存处理后的数据 handles.ocr_results = ocr_results; guidata(fig, handles); catch ME errordlg(sprintf('识别失败: %s', ME.message), '错误'); end end function clearResults(~, ~) handles = guidata(fig); % 清除结果文本 set(handles.formula_text, 'String', ''); set(handles.calc_text, 'String', ''); set(handles.answer_text, 'String', ''); set(handles.result_text, 'String', ''); set(handles.equal_log, 'String', {}); % 清除图像 axes(handles.ax_processed); cla; title('处理图像'); axes(handles.ax_equal); cla; title('等号检测'); % 如果有原始图像,重新显示 if ~isempty(handles.current_image) axes(handles.ax_original); imshow(handles.current_image); title('原始图像'); end end end % ======================== 运算符检测函数 ======================== function [is_operator, operator_type] = detectOperator(region_img) [h, w] = size(region_img); % 计算形状特征 aspect_ratio = w / h; eccentricity = regionprops(region_img, 'Eccentricity').Eccentricity; is_operator = false; operator_type = ''; % 减号检测 if aspect_ratio > 3 && eccentricity > 0.9 is_operator = true; operator_type = '-'; return; end % 加号检测 if aspect_ratio > 1.2 && aspect_ratio < 2.5 % 中心区域分析 center_y = round(h/2); center_x = round(w/2); % 检查水平和垂直线段 horizontal_line = sum(region_img(center_y, :)) > w*0.7; vertical_line = sum(region_img(:, center_x)) > h*0.7; if horizontal_line && vertical_line is_operator = true; operator_type = '+'; return; end end % 乘号检测(斜线) if aspect_ratio > 0.8 && aspect_ratio < 1.2 % 使用Hough变换检测斜线 [H, theta, rho] = hough(region_img, 'Theta', -45:5:45); peaks = houghpeaks(H, 2); if size(peaks,1) >= 2 angles = theta(peaks(:,2)); angle_diff = abs(diff(angles)); % 检查是否接近垂直的斜线对 if abs(angle_diff) > 80 && abs(angle_diff) < 100 is_operator = true; operator_type = '*'; end end end end % ======================== 数字校正函数 ======================== function char = correctDigit(region_img, original_char) [h, w] = size(region_img); % 1的特征:高宽比大,顶部无横线,底部较宽 aspect_ratio = h / w; top_region = region_img(1:round(h*0.3), :); bottom_region = region_img(round(h*0.7):end, :); top_pixels = sum(top_region(:)); bottom_pixels = sum(bottom_region(:)); % 7的特征:顶部有横线,右上角有折角 top_line = sum(region_img(1, :)) > w*0.6; right_top_corner = region_img(1, end) && region_img(2, end); if strcmp(original_char, '7') % 检查是否为1的特征 if aspect_ratio > 3 && top_pixels < numel(top_region)*0.2 && bottom_pixels > numel(bottom_region)*0.5 char = '1'; return; end elseif strcmp(original_char, '1') % 检查是否为7的特征 if aspect_ratio < 2 && top_line && right_top_corner char = '7'; return; end end char = original_char; % 保持原识别结果 end 这是所有的代码,现在的问题是,到第三步之前都没有问题,但是在识别字符时,是否是等号这个参数传递的不好,后续并没有识别到排序之后的等号,请根据这一点重新生成完整代码
最新发布
06-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值