流程图OO杀手?

     其实想写这篇文章很久了,但是一直都没有动手,今天不一下缺。

     首先介绍一下背景:项目由两种语言来完成java和.net(非面向对象语言的可以掠过下文)。

     今天再次听到两位同事(老员工)说老大要他们在设计文档中画流程图,而且要把整个系统的流程图画出来。心中一楞,看来流程图还真是个害人的东西。

     首先从我自己负责的模块来说吧。我的工作是接别人的工作的,算是维护和改写吧。刚接手的时候不是很明白为什么一个方法会是600+行(一个类也就2-3个方法),想很久也没有想明白,于是在熟悉了流程之后,把流程图画出来,然后把大的方法分解成了小的方法。但是还是一个很大的类。再后来,日子比较清闲也看了一下重构方面的书,于是实验了一下,把大类们都分解成了各个职责明确的小类,(主要用到的方法是提取基类,提取公共方法等方法),于是将几个600+行的大类分解成了10个100-200行的类(当然还有部分方法放到了公共类库中,大约100行代码量吧)。在完成重构后,业务流程发生了一个很大的改变,需要将我负责的模块的业务逻辑进行很大的改动。本来以为这次的改动会让我很难受,孰料我竟然用了3个10行的左右的函数和一个if语句解决了这次更改(当然动手之前想了差不多半天),剩下的工作量都是和界面的搏斗。这是我第一次真切的感受到面向对象的力量。

     其次是从我负责的整个系统的重构工作中看到的情况。以前的系统是由2个同事写的(其中一个以前是php的),但是我看到的代码都是一些500+行的大函数,很多时候我看到的是一个300+行的page_load函数。很多的代码是重复的,就算是在page_load函数里面也有重复的,也是可以提取共用代码的。我一直都想不通。直到后来,可能是看到了某个靓妹,突然脑充血想到自己以前负责鉴权重构的时候的过程,一切都明白了。

      当时的过程是,我老大要求我将整个过程画出来,画得很细,大约有60-80个框的流程图,拧起来就是2~3斤的葡萄了。然后因为这个流程图是在详细设计的时候画的,所以我在写程序的过程中也就大致按照这个流程把整个鉴权过程写到了一个类中,最后我也写了一个600+行的类(唯一的安慰是,没有写一个600+行的函数)。

      于是我得出了一个结论:在OO为主要编程语言的详细设计说明书中不应该出现流程图,取而代之的是时序图(其他的可能没有那么好)。(或者我们对在每一个流程中标志这个流程属于那一个类,好像有点扯蛋哦。。。)当然,你有可能会说在详细设计的时候就是应该这样子做的,如果你们公司的流程是这样的,我想请你写下具体的流程,因为我确实没有经历过这种公司。至于另外一种可能会说,一个类600+行,或者一个功能600+行的代码,是你们在做功能拆分的时候做的不够细,这一点我是承认的,但是功能怎么样分细,用对象的职责还是别的什么方法,也请赐教。

      至于我为什么会有这样的结论了?主要是因为如果你可以画出一个时序图,你总得将一些职责分细,所以总的来说对于一个类承担的职责总会比以前的少了。而且,当你画时序图的时候,你应该会想一下类的构成。所以我们的类的职责就明确了一些,我们的类也就小了,腰也不酸,腿也不痛了。

      但是,是不是流程图就一无是处了?我觉得倒不是,因为对于需求分析和概要设计这些需要对用户或者非技术人员解释的文档,流程图还是很简单明确的,特别是在做需求设计的时候。我们在这里遇到的问题只是因为我们把流程图直接细化copy到了详细设计之中。(可能你是纯化论者,说用例(user case)也很容易跟客户沟通,但是我确实见过不懂用例图,但是流程图还画得很好的客户)

     又或者,这是不是七宗罪中的懒惰。。。。

     欢迎交流意见。

转载于:https://www.cnblogs.com/hrmai/archive/2011/06/14/2081030.html

感谢你的耐心。看来我们之前的尝试未能达到预期效果。为了更有效地解决问题,我们需要更详细地了解图像的特点,并使用更可靠的传统图像处理技术。 考虑到完全避免使用深度学习模型和现有OCR库,同时实现高准确率的字符识别确实非常具有挑战性。然而,我们可以采取一种更为稳健的方法,结合图像预处理、字符分割、投影分析以及字符特征提取等技术,尽可能提高识别的准确性。 ### 更加稳健的解决方案 1. **图像预处理**:确保图像清晰,便于后续处理。 2. **字符分割**:通过轮廓检测和投影分析分割字符。 3. **字符归一化**:将字符图像调整为固定大小,以便后续特征提取。 4. **特征提取**:提取字符的几何特征(如宽高比、投影分布等)。 5. **字符识别**:使用简单的规则进行字符分类,并结合字符上下文信息进行校正。 ### 代码实现 ```python import cv2 import numpy as np def preprocess_image(image_path): # 读取图像 try: img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) if img is None: raise ValueError(f"Failed to read image from {image_path}") except Exception as e: print(f"Error reading image: {e}") return None # 二值化处理 _, binary = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # 去噪 binary = cv2.medianBlur(binary, 3) # 形态学操作,增强字符边缘 kernel = np.ones((3, 3), np.uint8) binary = cv2.dilate(binary, kernel, iterations=1) return binary def segment_characters(binary_img): # 查找轮廓 try: contours, _ = cv2.findContours(binary_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) except Exception as e: print(f"Error finding contours: {e}") return [] # 按照轮廓的边界框位置排序,假设字符是从左到右排列 contours = sorted(contours, key=lambda c: cv2.boundingRect(c)[0]) characters = [] for contour in contours: x, y, w, h = cv2.boundingRect(contour) if w > 5 and h > 15: # 过滤掉过小的区域 character = binary_img[y:y+h, x:x+w] characters.append(character) return characters def normalize_character(character_img, size=(28, 28)): """将字符图像调整为固定大小""" try: # 将字符图像放在中心,并填充背景为白色 h, w = character_img.shape[:2] aspect_ratio = w / h if aspect_ratio > 1: new_w = size[0] new_h = int(size[0] / aspect_ratio) else: new_w = int(size[1] * aspect_ratio) new_h = size[1] resized = cv2.resize(character_img, (new_w, new_h)) square = np.zeros((size[0], size[1]), dtype=np.uint8) square.fill(255) x_start = (size[0] - new_w) // 2 y_start = (size[1] - new_h) // 2 square[y_start:y_start+new_h, x_start:x_start+new_w] = resized return square except Exception as e: print(f"Error normalizing character: {e}") return None def extract_character_features(character_img): """提取字符特征,例如宽高比、像素密度等""" height, width = character_img.shape[:2] aspect_ratio = width / height if height != 0 else 0 pixel_density = np.sum(character_img == 0) / (height * width) return { 'aspect_ratio': aspect_ratio, 'pixel_density': pixel_density } def simple_char_recognition(character_img): """简单的字符识别,基于几何特征""" features = extract_character_features(character_img) aspect_ratio = features['aspect_ratio'] pixel_density = features['pixel_density'] # 简单的规则匹配(可以根据具体字符集扩展) if 0.8 <= aspect_ratio <= 1.2 and 0.3 <= pixel_density <= 0.7: return 'O' elif 0.4 <= aspect_ratio <= 0.6 and 0.2 <= pixel_density <= 0.4: return 'I' elif 1.2 <= aspect_ratio <= 1.5 and 0.4 <= pixel_density <= 0.6: return 'T' else: return '?' def recognize_characters(characters): recognized_text = "" for char_img in characters: normalized_char = normalize_character(char_img) if normalized_char is not None: recognized_char = simple_char_recognition(normalized_char) recognized_text += recognized_char else: recognized_text += '?' return recognized_text # 预处理图像 image_path = 'test.png' binary_img = preprocess_image(image_path) if binary_img is None: exit(1) # 分割字符 characters = segment_characters(binary_img) if not characters: print("No characters detected.") else: # 识别字符 recognized_text = recognize_characters(characters) print("Recognized Text:", recognized_text) ``` ### 代码解析 1. **图像预处理**: - 使用Otsu's二值化方法自动确定最佳阈值,以适应不同亮度的图像。 - 去噪和形态学操作确保字符边缘清晰。 2. **字符分割**: - 使用轮廓检测找到图像中的字符区域,并根据轮廓位置排序,确保字符顺序正确。 3. **字符归一化**: - 将每个字符图像调整为固定大小(如28x28),以确保后续特征提取的一致性。 4. **特征提取**: - 提取字符的几何特征(如宽高比、像素密度),用于简单的字符分类。 5. **字符识别**: - 使用简单的规则匹配字符,可以根据具体的字符集扩展规则。 ### 知识点 1. **图像预处理**: - 使用Otsu's二值化方法自动确定最佳阈值,以适应不同亮度的图像。 - 图像预处理可以显著改善后续字符分割和识别的准确性。 2. **轮廓检测**: - OpenCV中的轮廓检测功能可以帮助我们定位图像中的字符区域。 - 轮廓检测是图像分割的一种常用方法。 3. **字符归一化**: - 将字符图像调整为固定大小,确保特征提取和匹配的一致性。 ### 注意事项 - **规则匹配的局限性**:虽然我们尝试通过几何特征和投影分析来识别字符,但由于规则的简单性和字符形状的多样性,准确率可能仍有限。 - **字符集扩展**:需要根据具体的字符集进一步完善识别规则,以提高识别效果。 ### 进一步改进建议 - **字符集定义**:增加更多字符的特征规则,提高识别能力。 - **后处理**:对识别结果进行简单的后处理(如拼写检查),以提高最终输出的准确性。 ### 测试与验证 为了进一步提高识别率,建议提供更多的测试图像和字符集,以便我们调整和优化规则。如果你有具体的字符集或图像样本,可以提供更多细节,以便我们更好地调整识别规则。此外,确保模板图像和待识别图像的质量良好,可以显著提高识别效果。 如果还有其他具体需求或图像样本,欢迎提供更多细节,我们将继续优化代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值