TowardsDataScience 博客中文翻译 2019(一百一十四)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

全面的 TensorFlow.js 示例

原文:https://towardsdatascience.com/comprehensive-tensorflow-js-example-96367625fab7?source=collection_archive---------15-----------------------

这篇文章解释了如何在浏览器中使用 TensorFlow.js 运行机器学习。它涵盖了用于模型训练、迁移学习和预测功能的 TensorFlow.js API。有一个现场演示应用程序。它有助于预测业务报告执行等待时间。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: Pixabay

我已经实现了一个应用程序,其中包括 TensorFlow.js API 的使用。首先,我将向您介绍应用程序的功能,然后将深入实施细节。这个应用程序实现了一个业务报表执行时间预测用例(这次是用 JavaScript 实现的),在我之前的帖子中解释过——用 Keras 和 TensorFlow 实现报表时间执行预测。

对于模型训练,我使用 50 个历元(数据以 10 个为一批进行处理),学习率设置为 0.001。神经网络基于两个处理层和一个输出层。模型训练过程在浏览器中运行:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Model training process

应用程序已在此处部署并可用:

  • https://regressiontfjs-node.herokuapp.com/

模型被训练来预测业务报告执行的预期等待时间。实现是基于这本优秀的书— 深度学习与 JavaScript 和多元回归示例— Boston Housing 中的解释和材料完成的。

功能

第一次打开应用程序时,需要对模型进行训练。模型定型后,将保存到本地 indexeddb。浏览器重新打开后,该模型将仍然可以从 indexeddb 中获得,您可以选择它来重用或训练新模型(以前保存的模型将被替换)。

训练过程完成后,它将打印一组显示模型质量的变量:

  • 基线丢失:这是根据训练数据计算的平均平方误差。平方根值:237 秒。这意味着如果我们总是假设预测的平均值,误差范围将是 237 秒。
  • 平均时间:为训练数据计算的平均时间
  • 最终车组损失:训练期间计算的损失
  • 最终验证-设定损失:通过验证在训练期间计算的损失
  • 测试集损失:针对测试数据为训练模型计算的损失
  • 预测偏差(秒):测试集损失的平方根值。这说明模型错误。模型训练得很好,只有 4.5 秒的错误,比基线丢失好得多

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Model training

对以下数据运行预测功能—结果 514 秒:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Predict

将时间段更改为下午-预测时间将增加到 573 秒。这意味着模型根据训练数据进行了正确的训练,报告在下午运行的时间更长:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Predict

增加参数的数量。参数越多,需要处理的数据越少,报告运行速度应该越快。该模型通过返回更快时间的预测来证实这一点:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Predict

让我们更改报告 ID 和参数数量。观察预测时间:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Predict

现在我们将进行迁移学习——用新的目标重新训练模型(在这个例子中,为了简单起见,我只使用一行数据,但我建议用多行数据重新训练模型)。以下数据未包含在训练集中,这是一个新目标。呼叫训练法——它应该运行得非常快。测试集的损失可能会比基于原始训练的损失更严重(对本练习来说没问题),因为我们使用的是以前的测试集数据,而这些数据与新目标没有直接关系。新目标— 400 秒,对于报告 ID = 1(假设特定用户的时间不同于培训中的时间,并且该用户可以更新模型)。再培训(当我们在现有模型之上进行培训时——迁移学习)结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Transfer learning

重新训练模型后,对与之前相同的数字运行预测,您将看到预测结果将被调整并等于我们用于重新训练的目标:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Predict

现在,将报告 ID 更改为我们最初使用的 ID,将报告参数的数量以及时隙更改为原始值。您将会看到,现在我们预测的时间更短,这是由于最近的模型再培训,其中更短的时间被设定为一个目标:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Predict

尝试更改参数并查看结果。

实施

应用程序结构非常简单。所有逻辑都在 appController.js 中实现,UI 在 index.html 中实现。Web app 是用 Oracle JavaScript 库— Oracle JET 实现的。要在本地运行应用程序,请遵循以下两个步骤:

  • 使用 NPM 安装 Oracle JET:NPM install-g @ Oracle/ojet-CLI
  • 进入应用程序并运行:ojet restore
  • 运行应用程序:ojet serve

appController.js 中定义了一个监听器。当应用程序加载时,这个监听器被调用,它负责加载数据,将其转换为张量并计算基线。

数据通过助手模块 data.js 加载。我使用 Papaparse 库解析 CSV。原始数据集基于四列:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Data

我注意到模型不能直接从这些数据中得到很好的训练。报表 ID 和 daypart 列需要数据转换。这些列是分类的,并通过创建尽可能多的新列进行转换,因为存在唯一的分类值:

var features = results['data'].map(report => ({
 report_params: parseFloat(report.report_params),
 report_1: parseFloat(report.report_id) === 1 ? 1 : 0,
 report_2: parseFloat(report.report_id) === 2 ? 1 : 0,
 report_3: parseFloat(report.report_id) === 3 ? 1 : 0,
 report_4: parseFloat(report.report_id) === 4 ? 1 : 0,
 report_5: parseFloat(report.report_id) === 5 ? 1 : 0,
 day_morning: parseFloat(report.day_part) === 1 ? 1 : 0,
 day_midday: parseFloat(report.day_part) === 2 ? 1 : 0,
 day_afternoon: parseFloat(report.day_part) === 3 ? 1 : 0,
}));

这种数据转换有助于运行更精确的训练。我使用 1200 行数据进行训练,300 行数据进行测试。在将数据分成训练数据集和测试数据集之前,请确保对数据进行洗牌。我正在为这个任务使用 helper 函数,取自波士顿住房示例应用程序。

使用 TensorFlow.js 函数 tensor2d 将数据数组转换为张量:

tensors.rawTrainFeatures = tf.tensor2d(dataHelper.trainFeatures);
tensors.trainTarget = tf.tensor2d(dataHelper.trainTarget);
tensors.rawTestFeatures = tf.tensor2d(dataHelper.testFeatures);
tensors.testTarget = tf.tensor2d(dataHelper.testTarget);

TensorFlow.js 模型由两个处理层和一个输出层构成,用于返回预测值:

const model = tf.sequential();
model.add(tf.layers.dense({
 inputShape: [dataHelper.trainFeatures[0].length],
 units: 25,
 activation: 'sigmoid',
 kernelInitializer: 'leCunNormal'
}));
model.add(tf.layers.dense({
 units: 25,
 activation: 'sigmoid',
 kernelInitializer: 'leCunNormal'
}));
model.add(tf.layers.dense({ units: 1 }));

一旦构建了模型,编译它并运行 fit 函数来训练模型。我建议使用验证分割选项,这样在培训期间可以验证培训的质量:

model.compile({ optimizer: tf.train.sgd(LEARNING_RATE), loss: 'meanSquaredError' });await model.fit(tensors.trainFeatures, tensors.trainTarget, {
 batchSize: BATCH_SIZE,
 epochs: NUM_EPOCHS,
 shuffle: true,
 validationSplit: 0.2,
 callbacks: {
  onEpochEnd: async (epoch, logs) => {

函数 fit 提供 onEpochEnd 回调,我们可以记录训练进度并将数据推送到 UI。

训练完成后,通过对照测试数据运行模型来评估模型。从返回的数字中取平方根,这将是基于当前模型训练的以秒为单位的容许误差(如果结果不容许,尝试通过改变神经网络层的结构来重新训练模型,尝试调整训练参数):

result = model.evaluate(tensors.testFeatures, tensors.testTarget, { batchSize: BATCH_SIZE });
testLoss = result.dataSync()[0];

最后保存模型。有多个保存模型的选项,你甚至可以把它推送到服务器。在本例中,我将模型保存在浏览器的本地 indexeddb 中:

await model.save('indexeddb://report-exec-time-model');

模型训练好之后,我们就可以运行预测功能了。我正在从 indexeddb 中的保存状态加载回模型,构造输入张量并执行 TensorFlow.js predict:

model = await tf.loadLayersModel('indexeddb://report-exec-time-model');input = [{
 report_id: parseFloat(self.reportIdP()),
 report_params: self.reportParamsP(),
 day_part: parseFloat(self.reportExecSlotP())
}];convertInputToTensor(input);res = model.predict(tensors.inputFeatures);
score = res.dataSync()[0];

最后一步—转移学习,使用额外数据对现有模型进行重新训练(在这种情况下,数据形状是相同的,我们针对新目标进行训练)。为了使重新训练更有效,我们必须冻结原始模型的部分层。这样,先前训练的模型权重将不会受到影响,并且模型训练将运行得更快。通常,您应该使用多个新元素来运行培训,在这种情况下,为了简单起见,我使用一个新条目来运行培训。

通过将可训练属性设置为可以冻结模型层:

model = await tf.loadLayersModel('indexeddb://report-exec-time-model');model.layers[0].trainable = false;model.compile({
 loss: 'meanSquaredError',
 optimizer: tf.train.sgd(LEARNING_RATE)
});model.summary();input = [{
 report_id: parseFloat(self.reportId()),
 report_params: self.reportParams(),
 day_part: parseFloat(self.reportExecSlot()),
 exec_time: self.reportExecTime()
}];convertInputToTensor(input, 'Y');

在现有模型的基础上使用新数据运行拟合函数:

await model.fit(tensors.inputFeatures, tensors.inputTarget, {
 batchSize: BATCH_SIZE,
 epochs: NUM_EPOCHS,
 shuffle: true,
 callbacks: {
  onEpochEnd: async (epoch, logs) => {

资源:

大型制药公司的计算分析

原文:https://towardsdatascience.com/computational-analysis-of-big-pharma-investigating-the-effects-of-donations-to-docs-e9f43ef3a9bc?source=collection_archive---------27-----------------------

深入分析

调查“捐赠”给医生对药物处方的影响

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by JOSHUA COLEMAN on Unsplash

“我会记住,我治疗的不是发烧表,不是癌变,而是一个生病的人,他的病可能会影响这个人的家庭和经济稳定。如果我要充分照顾病人,我的责任就包括这些相关的问题。”

——现代希波克拉底誓言

每年,在期待已久的毕业庆典中,希波克拉底誓言的话语——医学专业人士几个世纪以来做出的古老承诺——回荡在各国医学院的大厅里。这些神圣而受人尊敬的机构将数千名聪明的毕业生送到美国各地,以减轻痛苦,改变生活,在某些情况下,有希望拯救他们。

但是,如果这些毕业生进入一个越来越受金钱驱动、越来越不受关怀驱动的体系,那该怎么办呢?如果这些聪明的年轻男女是大型制药公司运作的大规模赚钱计划的目标呢?如果大型制药公司更多地瞄准特定的医学专业,那会怎么样?为什么会这样?

在 20 世纪 60 年代,美国人对医疗行业的信任度达到了空前的高度。当时,超过四分之三的美国人对医学领袖非常有信心。今天,只有 34%的美国人这样做。随着数千家制药公司每年向全国各地的医生“捐赠”数十亿美元,美国人对医疗行业的信任度应该会更低吗?

研究问题

有时间的话,看看左边的视频。说真的,看着点。该视频揭示了数百万美国人不知道的看似腐败的系统。每年,制药公司以“教育”为名,向医师提供 数十亿 美元的“捐款”

如果您到了这一步还没有观看视频,我们恳求您返回并点击播放。如果不是为了宣布医疗/制药领域普遍、持续的腐败,至少看看约翰·奥利弗带来的喜剧价值。眼前的问题是复杂的、多层次的和多方面的;这个视频会让你对它的理解产生奇迹。

现在让我们回到手头的问题上来。

从局外人的角度来看,这整个系统听起来似乎是无辜的——公司教医生关于他们的药物,这样医生就可以对他们给病人开的药物做出明智的决定。这有什么不好?

但是,当 FDA 对仿制药和品牌药的要求出现时,这个无辜的框架就变得模糊了:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

FDA requirements for generic vs. branded drugs

等一下。你是说学名药在法律上要求在各方面与品牌药本质上相同?当学名药平均比品牌药便宜 80-85%时,为什么会有人选择品牌药而不是学名药呢?

嗯,这种看似错误的行为有三种可能的情况:

  1. 一家制药公司开发了一种专利药物,并拥有该药物的专利垄断权。这些专利的长度受到国会的限制,并且应该最终让位于相同的、便宜得多的仿制药。嗯,除非发生这样的事:

“……拥有品牌药品的公司将通过拒绝交出生产仿制药所需的样品和安全协议来阻止仿制药进入市场。这种策略人为地延长了制药公司的专利,违背了国会鼓励仿制药的意图。"-openmarketsininstitute

我们没有足够的时间、天数、周数(你可以想象)去冒险进入专利垄断和大型制药公司的国会游说努力的兔子洞。但是,如果你真的很好奇,可以看看这个链接。

2.一名患者特别是在药店要求购买一种品牌药,而不是一种相同的仿制药(可能是因为电视广告或他们的邻居 Karen*的推荐,Karen *服用立普妥并对其深信不疑)。

3。医生专门给开一种品牌药,而不是仿制药。

场景#3 是事情变得真正令人兴奋的地方,也是我们研究的重点。

我们看着场景#3,问自己 为什么。

还记得开头引用的希波克拉底誓言吗?当医生发誓要了解疾病对患者“经济稳定性”的影响时,他们为什么会开品牌药而不是仿制药?

再加上奥利弗先生在上文指出的数十亿美元的“捐赠”系统,这就产生了一个引人注目、具有社会影响力和重大意义的研究问题:

研究问题:大型制药公司的捐赠会影响医生给病人开的特定药物吗?

通过我们的研究,我们开始了解大型制药公司直接支付给医生的费用可能会对你、我和凯伦最终服用的处方药以及我们支付的价格产生的影响。

研究过程

因此,我们耳听八方,倾听医疗腐败的最轻微的迹象,开始了一场勇敢的探索,以揭示广泛的社会弊端,并由此引发广泛的社会变革。

至少我们是这么想象的。

我们“撞上”的直接障碍与可用数据的绝对规模、数据集的格式以及处方填写过程中涉及的微小法律/程序复杂性直接相关。

但是现在没时间了…我们会在路上讨论的。

数据集

我们根据三个关键数据集构建了我们的研究:

  1. 公开支付 —接受 2013 年至 2017 年间对医生的捐赠
  2. 医疗保险提供者利用和支付数据—2013 年至 2017 年作为医疗保险一部分的所有处方
  3. 处方药、制造商及其价格

下载每个数据集后,我们很快意识到我们正在处理的数据的巨大规模。仅开放支付数据表就包含数千万行。医疗保险提供者利用率数据表包含超过 1 亿行。

数据是彻底的,这是肯定的。但对我们的目的来说是可管理的?不完全是。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Alexander Sinn on Unsplash

我们决定将我们的研究细化到日历年 2016 。这大大地把数据精简到了一个稍微容易管理的状态。开放支付数据被限制在大约 1090 万行,而医疗保险提供者利用数据(从这里开始称为“处方数据集”)被限制在大约 2430 万行。即使这些受限的数据集对于我们微不足道的 8GB 内存来说也太多了,无法在合理的时间内处理;计算时间内存使用量在我们尝试使用数据集的每个过程中都被放大了,特别是在数据集之间移动时(例如,从开放支付数据集中提取一个接受捐赠的医生,并在处方数据集中搜索同一医生的出现次数)。为了帮助解决这些问题,我们使用了Daskdata frames 来“延迟”加载数据(直到对该数据执行了计算,才将数据加载到内存*)。*

我们研究过程的第二步是清理数据。这一步花费了惊人的时间和精力,我想这证明了数据科学花费了多少时间来定制一个或多个数据集以满足您的特定研究需求。我们清理数据的方法包括:从所有三个数据集中删除不必要的(出于我们的目的)列,合并我们需要合并的某些列(例如,名字、姓氏),处理 NaN 值,删除区分大小写,合计每个医生的支付总额,以及一系列其他整理任务。

主要发现

清理之后,我们开始从数据中对我们的研究问题做出有意义的结论。我们知道我们仍然在处理一个相当大的数据集,所以我们决定专注于数据的目标子集:医疗专业。捐赠给哪些医学专科最多,为什么?

为了进行调查,我们重点关注了 2013 年至 2016 年间向医生捐赠超过 1 亿美元的 20 家制药公司。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Propublica Dollars for Docs

然后,我们查询开放支付数据集,按医生专业对捐赠进行分组,然后找到每个医疗专业的平均捐赠价值。我们希望这一过程能准确揭示出最大的制药公司把大部分资金花在了哪个医学专业上。

这里有一个很好的图表来说明这些发现(使用平均值):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Note: Shows top-20 receiving specialties

当你侧着头观看剧情时,很明显儿科 重症医学在平均捐赠价值方面击败了其他专业。我们发现这非常令人惊讶!我们期望矫形外科在平均值和总价值方面是最高的;骨科手术在捐赠的总净值方面排名第一(见下图),而在捐赠的平均价值方面仅排名第五。

这是使用总捐赠价值的图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Note: Shows top-20 receiving specialties

为什么会这样?为什么最大的制药公司会如此强烈地针对儿科急救护理专家?

我们最初对这些结果的论证集中在儿科急诊专业的性质上。这些医生专门护理处于紧急情况下的儿童。因为紧急事件通常是时间敏感的,这些医疗专业人员可能有完全酌处权决定儿童服用何种处方药。在这种情况下,我们的意思是,在儿科急救护理专家倾向于的特定情况下,父母可能会将完全的决定权交给可信任的专家,而不会争论是否要开品牌药或仿制药。当吉米因为手臂骨折而尖叫时,妈妈和爸爸可能不会为一种药物的品牌名称而争吵;他们只是希望尖叫停止,他们美丽的男婴再次成为 5 岁健康的形象。

如果是这种情况,并且制药公司理解这一点,那么大型制药公司让儿科急救护理专家以任何必要的成本开出所有品牌的药物是有意义的,包括进行大量捐赠。

但是,当你可以查询数据并做出有根据的结论时,为什么要做出没有根据的结论呢?

然后,我们通过直接检查儿科急救护理专家和整形外科医生开出的特定药物来结束这个循环。我们这样做是为了调查这些大量捐赠是否真的影响了医生开的特定药物。

上面,我们确定儿科急救护理专家从大型制药公司获得了大量现金(好吧,是的,这些“捐赠”被标为“演讲费”和“所有费用都由我支付的医学会议旅行”,但在这一点上,我们只需滚动),现在让我们看看这些现金是否有所回报。

为了对此进行调查,我们:

  1. 儿科急诊专家处方数据集索引
  2. 找到每位儿科急救护理专家开出的所有 Medicare 部分处方的结果集

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Step 2: grouping prescriptions by prescriber. Prescribers are members of specialty most targeted for donations (pediatric emergency care or, separately, orthopedic surgery)

3.遍历每个医生的处方集,如果处方是品牌药而不是仿制药,则标记处方

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Step 3: Branded drugs prescribed by orthopedic surgeons

4.交叉引用“药物和制造商”数据集中的品牌药物,查看是否由被调查的前 20 家公司之一制造。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Step 4: Branded drugs prescribed by pediatric emergency care specialists that were manufactured by the companies investigated

5.如果医生开了一种品牌药物,我们随后使用医生的名字查询开放支付数据集,以查看特定医生是否接受了制药公司的捐赠。通过这样做,我们将能够在某种程度上检验药品捐赠对药物处方的可能影响。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Step 5: Orthopedic surgeons who prescribed branded drugs, those branded drugs were manufactured by the companies in question, and they were donated to by those companies. Includes value of donation.

6.对研究的第二个专业重复步骤 1-5:矫形外科。

好吧……那你发现了什么?

至少可以说,我们的结果令人惊讶。

在儿科急救护理专家和整形外科医生身上执行上述过程后,我们发现:

2016 年品牌儿科急诊专科处方数量:4

开品牌药的儿科专家接受药品制造商捐赠的人数(被调查的 20 家公司之一):0

2016 年品牌骨科手术处方数量:568

开品牌药的儿科专家接受药品制造商捐赠的人数(被调查的 20 家公司之一):4

嗯……真令人失望。

也可能不是,看你怎么看!如果这些发现成立,看来药品捐赠在影响医生处方决策方面并不像假设的那样有效。嘿,这对所有人来说都是好消息。

我们的研究表明,在 2016 年,对于从 20 家支出最高的制药公司获得最高平均捐赠值和最高净捐赠值的专科(儿科急诊和骨科手术),相关性最小。简单来说,捐赠似乎并没有明显影响处方中的特定药物。

结论和警告

但是,沉住气。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Kai Pilger on Unsplash

这些发现伴随着一些我们想要解决的重要警告。在进行研究的许多时候,我们遇到了数据的问题和限制。

首先也是最重要的,处方数据集的性质。

该处方数据集仅限于联邦政府 2016 年的联邦医疗保险 D 部分支出。虽然这一系列数量庞大,但它只代表了 2016 年美国完成的总处方的一小部分。医疗保险是一个政府项目,因此,它的记录对公众是免费的。这就是我们使用它们的原因。这个研究项目并不是决定性的,因为它只是检查了整个药品市场的一小部分样本。

小规模的抽样来模拟大规模的行为可能对一些研究有用,但是医疗保险的某些特征进一步搅浑了我们的研究水域。因为医疗保险是一个政府项目,它带有限制和局限;这些限制在“D 部分”级别变得更加精炼和严格。“D 部分”是指医疗保险计划的特定子集,仅涵盖六类药物:抗抑郁药、抗精神病药、抗惊厥药、抗逆转录病毒药物(艾滋病治疗)、免疫抑制剂和抗癌药物。这立即给我们的儿科调查带来了问题,并可能解释为什么我们发现如此少量的品牌儿科药物处方。

此外,医疗保险的资金受到联邦政府的限制。因为政府的目标是将医疗保险支出保持在最低水平,同时仍然向公众提供必要的药物,他们可能会压倒性地将已完成的处方限制为非专利药物,而不是品牌药物。这也可以解释为什么我们在研究中很少发现品牌药物处方。

最后,不是所有的医生都接受医保。医生必须选择接受医疗保险,当平均而言,医疗保险只支付私人健康保险的 80%时,它似乎越来越不受欢迎。已经对利润最大化感兴趣的医生可能不会选择接受医疗保险,因此不会出现在我们的数据集中。这些医生可能是从制药公司获得最多捐赠的人。

另一方面,我们的研究仅限于调查前 20 家捐赠制药公司。我们做出这个决定是因为它使数据更容易管理和使用。然而,这些公司可能全部或大部分专注于医疗市场的特定领域(即,它们生产儿科医生和整形外科医生永远不会使用的药物)。因为我们遗漏了几十家其他较小的公司,我们可能错过了儿科/骨科药物的制造商。

所有这些观察都指向一个真理,这个真理在这个研究过程的每一步都在我们的脑海中回荡:感知到的药品捐赠问题极其微妙和模糊。在项目开始时,我们从来没有想象过我们必须考虑制药公司、医生、药剂师和患者可能做出的实际决定的次数——所有这些都是为了对我们面前的数据做出有意义和有效的声明。问题的规模、围绕公开披露某些支付/处方而非其他支付/处方的法律问题,以及使用多个数据集(每个数据集都以不同的方式对其数据进行编码,并且由不同的团队创建/管理)使该研究项目具有挑战性…但也很有趣。

但是为什么调查这些真的很重要呢?

如果你已经到了这一步,还没有找到自己对上述问题的答案,下面是我们的看法,简单明了:

生命可能危在旦夕。

如果医生给病人开错了药(因为偏向大制药公司),疾病可能得不到充分的控制,症状可能蔓延,治疗可能无效。人们可能会死。

进一步研究的课题

我们的项目仅仅触及了使用 OpenPayments 和 Medicare 部分数据集的可能性的表面。这些数据集是彻底的,强大的,令人印象深刻的,研究的机会是无限的。

我们讨论了调查大型制药公司捐赠对研究出版物的影响。例如,如果 Dave 医生接受了一家生产药物 A 的制药公司的捐赠,那么他以后写/合著一篇吹捧药物 A 的积极作用的研究文章的可能性有多大?这个问题很重要,因为成千上万的医生和患者依靠医学期刊来了解市场上出现的新药的好处/坏处。基于这些文章,医生开出特定的药物。

为了回答这个问题,我们可以使用自然语言处理来按语气(积极/支持或消极/不支持)对研究文章进行编码,并搜索开放支付数据集以查找对文章作者的捐赠。然后,我们可以使用情绪分析分数以及对开放支付数据集的查询来使用线性回归。

此外,我们对使用机器学习来基于医生的多个特征(例如,美国所在的州、从业年限等)预测医生可能收到的捐赠的预计金额感兴趣。).我们特别想调查大型制药公司捐赠的具体形式是否会影响处方偏见。如果 good ol’ Dave 医生每年从 FakePharma,Inc .获得 150 份免费午餐,他是否更有可能开 FakePharma,Inc .的药,而不是每个周末 FakePharma,Inc .带他去参加医学会议?

我们使用的所有数据集都是免费使用/下载的;如果你对可能的进一步研究课题有任何想法,不要害怕投入进去!

我已经走了这么远,现在怎么办?

很棒的问题!这里有一些步骤,你可以马上采取,以更好地保护自己和你爱的人免受潜在的偏见处方。

  1. 我们恳请你在美国政府的开放支付网站或 ProPublica 的 Dollars for Docs 网站上查找你的医生,并认真考虑你对他/她的信任。
  2. 我们强调建议阅读进入同行评审的关于特定药物有效性的医学研究。不要仅仅依赖电视广告告诉你的或者前几天晚上凯伦推荐的炒鸡蛋。

做你自己的研究,并把研究带到你医生的办公室。首先,试着看看发表在 CDC 预防慢性疾病杂志或其他类似杂志上的发现。

对于那些永远读不够的人来说,这是额外的读物

1.掉进兔子洞:高药价和专利垄断

2.大型制药公司花费数百万游说反对降低处方药价格

3.加拿大啊,你也有这些问题!

4.大型制药公司是否加剧了阿片类药物危机?

5.类似的调查研究!—制药行业为医疗保险受益人赞助的膳食和医生处方模式

这里有一些主题音乐,你可以在拥护制药透明度和公平性的时候听听

这个项目是由我、西西佛·津加和查理·朱尼尔·奎宁与❤共同完成的。如果你有兴趣复制我们的研究项目来调查你自己的燃眉之急的大型制药公司的问题,这里有我们的 GitHub 和代码/文件

*Karen 是本文中虚构的人物,仅用于解释/描述目的

计算生物学

原文:https://towardsdatascience.com/computational-biology-fca101e20412?source=collection_archive---------13-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(Image reproduced from: https://blog.f1000.com/2017/02/01/f1000prime-f1000prime-faculty-launch-bioinformatics-biomedical-informatics-computational-biology/)

计算生物学是数学、统计学和计算机科学的结合应用,用于解决基于生物学的问题。生物学问题的例子有:遗传学、进化论、细胞生物学、生物化学。[1]

介绍

最近的技术进步使我们能够存储数量惊人的数据。最初,**【大数据】**被感知为待解决的问题。事实上,我们已经到了能够存储太多数据却不能充分利用的地步。这推动了对数据科学和人工智能进步的需求。

如今,最初被认为是一个问题的东西,现在已经成为一扇通向创新世界的大门。大数据使计算机视觉和深度学习等许多研究领域蓬勃发展。这使得机器能够执行复杂的决策任务,并从原始数据中提取人类肉眼看不到的信息。

生物学是一门广泛使用生物数据库来尝试解决许多不同挑战的学科,例如理解疾病的治疗和细胞功能。生物数据的数据集可以由氨基酸序列、核苷酸、大分子结构等创建。

此外,计算机科学中经常使用的许多机器人系统和算法都是受生物复合体的启发。例如,深度学习神经网络在原理上受到人类大脑结构的启发。

计算生物学算法

计算生物学中使用的算法的一些例子是:

  • 全局匹配
  • 局部序列匹配
  • 隐马尔可夫模型
  • 群体遗传学
  • 进化树
  • 基因调控网络
  • 化学方程式

全局匹配(也称为 Needleman-Wunsch 问题)和局部序列匹配(也称为 Smith-Waterman 问题)利用我们对一种生物的蛋白质的知识来了解更多关于其他生物的蛋白质。

马尔可夫模型用于模拟序列。在这些类型的模型中,事件发生的概率仅仅依赖于其先前的状态(例如,这种类型的模型可以用于对 DNA 序列建模)。隐马尔可夫模型(图 1)使用概率有限状态机,根据我们所处状态的概率,我们发出一个字母,然后转移到下一个状态。下一个状态可能等于初始状态。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 1: Hidden Markov Model [2]

群体遗传学试图模拟进化。为此,它通常使用费希尔-赖特模型。该模型试图模拟在选择、突变和交叉条件下基因位置发生的情况。

进化树(图 2)可以基于某种形式的进化距离来创建。进化树主要有两种类型:基于距离的树和基于序列的树。进化树被用来解释不同物种之间的距离。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 2: Evolutionary Trees [3]

基因调控网络由于生物体内不同蛋白质的相互作用而形成。不同的蛋白质相互控制,根据它们相互作用的性质,决定了细胞的类型。

化学方程式(图 3)终于可以用来描述基因调控网络背后的机制。反应速率取决于化学方程式中元素的浓度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 3: Chemical Equations [4]

用于生物预测的机器学习

在计算生物学中使用机器学习现在变得越来越重要(图 4)。目前的应用是基因组学(研究有机体的 DNA 序列)、蛋白质组学(更好地了解不同蛋白质的结构和功能)和癌症检测。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 4: Machine Learning workflow in Biological Data Analysis [5]

研究人员证明,使用卷积神经网络(CNN)和计算机视觉,通过图像分类进行癌症检测,可以获得可观的分类精度[6]。

几个数据集可以在网上公开获得,以开始生物数据探索,一个例子可以是 xenabrowser.net。这些数据集由加州大学圣克鲁斯分校的 UCSC·谢轩提供。

联系人

如果你想了解我最新的文章和项目,请通过媒体关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:

文献学

[1]计算机科学学位中心。访问于:https://www . computersciencedegreehub . com/FAQ/what-is-computational-biology/,2019 年 5 月。

[2]隐马尔可夫模型。访问时间:https://en.wikipedia.org/wiki/Hidden_Markov_model,2019 年 5 月。

[3]蝙蝠和猿:自然历史博物馆的互动桌面游戏。迈克尔·s·霍恩等人访问:https://www . research gate . net/publication/254004984 _ Of _ BATs _ and _ APEs _ An _ interactive _ desktop _ game _ for _ natural _ history _ museums/figures?lo=1,2019 年 5 月。

[4]化学文献。4.1:化学反应方程式。访问:https://Chem . libre texts . org/Courses/bellar mine _ University/BU % 3A _ Chem _ 103 _(Christianson)/Phase _ 1% 3A _ Chemistry _ Essentials/4% 3A _ Simple _ Chemical _ Reactions/4.1% 3A _ Chemical _ Reaction _ Equations,2019 年 5 月。

[5]拥抱。计算生物学的深度学习。Christof Angermueller、Tanel Pä rnamaa 等人。访问时间:http://msb.embopress.org/content/12/7/8782019 年 5 月。

[6]胡子龙嘎,唐金山,等。基于图像的癌症检测和诊断的深度学习,一项调查。查阅于:https://www . science direct . com/science/article/ABS/pii/s 00313203183018452019 年 5 月。

计算机设计的人类——试管中的人工智能革命

原文:https://towardsdatascience.com/computer-designed-humans-the-ai-revolution-in-the-test-tube-fe8764d5f44b?source=collection_archive---------16-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

忘掉自动驾驶汽车和声控扬声器吧:未来几年,人工智能最引人注目的效果将出现在一个非常不同的领域。

这些天来,总是有来自科学界的报告,它们的交叉联系和后果并不明显。最近的一个例子可以在最新一期的《自然》杂志上找到。它涉及一种称为白细胞介素-2 的蛋白质,理论上有望成为针对某些类型癌症的免疫疗法的非常有趣的新可能性。然而,白细胞介素-2 有一个主要缺点:虽然它是一种内源性物质,但大量使用时毒性很大。

“想象一下,在未来,由于拥有特权基因,更有钱的人会活得更长久、更健康。”

更稳定,危害更小,看起来完全不同

在《自然》杂志的文章中,丹尼尔-阿德里亚诺·席尔瓦和 20 多名同事报告了他们如何开发出一种设计版本的白细胞介素-2,减少这些不利的特性或使它们完全消失。它可以用来治疗小鼠的肠癌和皮肤癌。一种基于人体自身物质的人造蛋白质,可能在几年内用于癌症治疗,在实验室中创造,现在它正在到来:用一种“计算方法”。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

设计师蛋白质是在复杂的迭代过程中产生的,在计算机上和实验室中交替进行。最终,它几乎看起来不像原来的,但毒性更低,甚至比原来的更稳定。

实现蛋白质计算的软件叫做 Rosetta。它的发明者是这篇文章的作者之一。华盛顿大学的大卫·贝克是这门新学科的先驱之一,这门学科可以被称为计算生物技术:使用复杂软件分析、预测和设计蛋白质结构。或者,换句话说:在这里,生物体的组成部分在计算机上被分解、预测、解释和构建。

折叠一次活鹤

近年来,Rosetta 在 CASP 竞赛的背景下被反复使用,这已经是几周前讨论的话题。比赛的焦点是哪一个团队最有能力从给定的 DNA 序列中预测三维蛋白质结构。一个非常复杂的任务,书呆子漫画家兰道尔·门罗曾经解释如下:

“你折过纸鹤吗?“现在想象一下,你必须弄清楚哪些褶皱是制作一只真正的活鹤所必需的”。

在最近的 CASP 比赛中,有一个来自场外的惊喜赢家。谷歌——或者更确切地说是字母表——的女儿 Deepmind 的十人团队迄今为止击败了这个学科的领导者。Deepmind 开发了一个名为 AlphaFold 的系统,该系统基于人工神经网络。这是在人工智能领域给我们带来快速进步的技术。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

蛋白质文件夹的身份危机

正如遗传学家 Mohammed Al-Quraishi 在一篇值得注意的博客文章中所报道的那样,Deepmind 的胜利让国际蛋白质折叠界的许多明星陷入了危机。起初,许多同事担心 Deepmind 会因为一种别出心裁的新方法而失去专家。然后是救济:方法和工具是新的,但不是基本的方法。然后,他们开始诋毁成功,并将其归结为他们所使用的资源。

这让我想起了职业围棋选手对 Deepmind 的 AlphaGo 在比赛中首次战胜欧洲冠军的反应:嗯,毕竟没有那么伟大。都只是计算能力。反正真正的专业人士更好。后来发生的事情,现在已经尽人皆知。

人工智能现在可以做到这一点

Deepmind 团队并不是唯一一个将机器学习方法应用于此类任务的研究小组。谷歌子公司无疑比大学研究人员拥有更多的资金和计算能力。然而,这个结果的精髓在我看来是不同的:AI 现在可以做这样的事情。忘了拥有语音识别和自动驾驶汽车的扬声器吧:人工智能将很快带来生物技术领域可能最剧烈的变化。

DNA 是数据,蛋白质结构是数据。这里要解决的问题极其复杂,涉及多因果、复杂的关系、结构和模式。这些都是今天的人工智能,甚至是明天的人工智能可以有效处理的事情。学习系统不仅建立起来了,而且已经准备好了——如果你继续训练它们,并进一步强化它们,它们会继续改进。

一场我们还不敢梦想的科学革命

这种生物技术和机器学习的结合很可能会在未来几年引发一场我们连做梦都不敢想的科学革命。这场革命将要发生的学科并没有为此做好准备。哈佛大学的系统生物学家 Al-Quraishi 写道:“尽管在工业研究实验室中发挥着核心作用,但在软件和计算机科学方面具有专业知识的研究工程师几乎完全不在学术实验室中。”

因此,有可能一小群有才华的不合群者突然在几十年的研究传统中处于领先地位。不仅学术界对此感到惊讶,而且大型制药公司也感到惊讶——即使他们似乎睡着了,尽管他们有必要的资金将机器学习作为一种研究工具。

设计人的机器?

这种情况现在可能要改变了。辉瑞、默克、诺华等公司现在将为人工智能专家发布许多高薪职位的广告。然而,Deepmind 的人不会停止对这个久负盛名的东西的研究。

公司和大学将很快开始生产由学习机器开发或至少在学习机器的帮助下开发的设计师分子。接下来,机器将为基因治疗干预提出建议。那些生命能够被挽救或延长的病人会很高兴。

此外,在某个时候,可能是从地球上某个地方的秘密实验室,第一个设计师 DNA 将从机器中出来。

电脑说没有

原文:https://towardsdatascience.com/computer-says-no-52a9c31cb8f2?source=collection_archive---------46-----------------------

如果你是《小英国》的粉丝,你可能会熟悉这篇文章的标题,因为在不同的草图中,一个人在台式电脑中输入一些数据,直到“电脑说不”。

我目前正在使用这些短视频中的一些作为一种有趣的方式来介绍我们今天在与人工智能系统合作时面临的主要挑战之一:算法透明

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

everis AI ethics framework. All rights reserved.

可解释的人工智能,或 XAI ,是机器学习模型理解、信任和管理自动决策系统的必要条件。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: https://www.darpa.mil/program/explainable-artificial-intelligence

根据 DARPA 的说法,通过 XAI,“新的机器学习系统将有能力解释它们的基本原理,描述它们的优缺点,并传达对它们未来行为的理解。实现这一目标的策略是开发新的或改进的机器学习技术,这将产生更多可解释的模型。这些模型将与最先进的人机界面技术相结合,能够将模型转化为最终用户可以理解和有用的解释对话”。

对于人工智能可能对人类产生重大影响的任何关键系统人工智能应允许用于:

  • 为任何决策重新创建结果
  • 了解用于训练模型的逻辑和数据
  • 确保自动化决策的可追溯性和可审计性

如果我们的人工智能系统符合这些要求,我们将不仅确保可解释性,而且确保可追溯性,允许建立反馈循环,这有利于我们的人工智能系统,同时保护它们免受偏见等其他挑战,以及将我们从可解释的人工智能转移到可追溯和透明的人工智能

最后,为了增加对人工智能系统的信任,我们需要以一种清晰、准确和可行的方式与我们的用户和利益相关者沟通。为了做到这一点, 将设计原则和团队视为我们人工智能产品生命周期的基础部分将是关键。

毫无疑问,信任是最有价值的商业商品,所以我们不能让一台计算机代表我们公司做出决定,而不理解其中的原因,也不能有效地与客户沟通。

如果你喜欢阅读这篇文章,请 考虑成为会员 ,在支持我和媒体上其他作者的同时,获得每个故事的完整访问权限。

计算机视觉——从 CNN 到面具 R-CNN 和 YOLO 之旅——第一部分

原文:https://towardsdatascience.com/computer-vision-a-journey-from-cnn-to-mask-r-cnn-and-yolo-1d141eba6e04?source=collection_archive---------3-----------------------

在本文中,我们将探索和了解不同计算机视觉算法 CNN 的架构和工作方式,基于区域的 CNN(R-CNN),快速 R-CNN,更快 R-CNN。在下一篇文章中,我们将探索面具 R-CNN 和 YOLO(你只看一次)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

计算机视觉的目的是什么?

计算机视觉是人工智能的一个分支。它用于使计算机能够像人类视觉一样理解、识别和生成对数字图像的智能理解。

计算机视觉是干什么的?

利用计算机视觉,我们可以识别

  • 图像中存在的特征如边缘检测。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Edge detection

  • 对图像中存在的物体进行分类。给图像分配标签,就像识别图像中的猫和狗或对数字进行分类

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image classification of digits

  • 图像分类和定位。这包括对图像进行分类,以及识别物体在边界框中的位置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 对象检测识别图像中出现的所有不同对象及其位置。围绕图像中出现的所有对象绘制一个边界框。检测是识别图像中存在的内容。定位是指物体在图像中的位置

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: http://www.robots.ox.ac.uk/~tvg/publications/talks/fast-rcnn-slides.pdf

  • 对象分割或语义分割在像素级检测图像中存在的所有对象。输出具有不同类别或对象的区域

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Semantic Segmentation of two people riding a bike in front of a building

  • 神经风格转移我们通过学习一幅图像的风格并将其应用于另一幅图像来生成一幅新图像

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Neural Style Transfer

利用卷积神经网络(CNN)进行图像分类是如何工作的?

当我们观看图像时,我们扫描图像。我们可以从左到右或从上到下查看图像,以了解图像的不同特征。我们的大脑结合我们扫描的不同局部特征来对图像进行分类。这正是 CNN 的工作方式。

CNN 将输入作为图像“x”,这是一个具有不同颜色通道(红色、绿色和蓝色-RGB)的二维像素阵列。

我们对输入图像应用不同的滤波器或特征检测器来输出**特征图。**与输入图像相比,过滤器或特征检测器在空间上很小。这些滤波器贯穿输入图像的整个深度。

通过对卷积层应用非线性函数 ReLU,并行执行多次卷积。

多特征检测器识别不同的东西,如边缘检测,不同的形状,弯曲或不同的颜色等。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们将池应用于卷积层。我们可以应用最小池、最大池或平均池。与最小或平均池相比,最大池功能提供了更好的性能。

汇集有助于**平移不变性。**平移不变性意味着当我们少量改变输入时,汇集的输出不会改变。

图像的不变性意味着,即使当图像被旋转、调整不同大小或在不同照明下观看时,一个对象也将被识别为相同的对象。

在下一步中,我们将合并层展平,以将其输入到全连接(FC)神经网络。

我们在全连接层的最终输出层中使用 softmax 激活函数进行多类分类。

对于二元分类,我们在全连接层的最终输出层中使用 sigmoid 激活函数。

CNN 的实力

CNN 用于

  • 图像分类
  • 使用包围盒的目标检测

CNN 的局限性

  • 使用边界框进行对象检测,但一次只能检测一个对象
  • 由于干扰,当多个物体在视野中时,效果不好。

那么我们如何识别一幅图像中存在的多个对象,并在所有不同的对象周围绘制边界框呢?

我们现在探索基于区域的 CNN,这将有助于解决图像中存在多个对象的问题,并在所有不同的对象周围绘制边界框。

基于区域的 CNN- R-CNN

R-CNN 用于分类,以及利用图像中存在的多个对象的边界框进行对象检测

R-CNN 是如何工作的?

R-CNN 工作的前提是,在给定的区域中,只有单个感兴趣的对象将占主导地位。

R-CNN 使用选择性搜索算法进行目标检测,以生成区域建议。

那么是什么在一幅图像中形成了一个区域呢?

图像中的区域可以通过以下方式识别

  • 变化的颜色
  • 不同的尺度
  • 不同的纹理
  • 不同外壳

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Identifying different objection based on regions

图(a),勺子,碗都是不同比例的。图(b),小猫是基于颜色而不是纹理来区分的。图(c ),变色龙可以通过纹理来区分,但不能通过颜色来区分。图(d),车轮是汽车的一部分,但颜色或纹理不相似。它们是外壳的一部分。

什么是选择性搜索,我们将如何使用它来识别图像中的多个对象?

选择性搜索

  • 使用自下而上的图像区域分组来生成从小到大的区域层次结构
  • 目标是生成一小组高质量的对象位置
  • 结合了细分和穷举搜索的最佳直觉。
  • 图像分割利用图像的结构来生成对象位置
  • 穷举搜索旨在捕捉所有可能的对象位置

选择性搜索与穷举搜索逐步工作

步骤 1: 生成初始子分割。我们生成尽可能多的区域,每个区域最多属于一个对象。

第二步:**递归地将相似的区域合并成更大的区域。**这里我们使用贪婪算法。

  • 从该组区域中,选择两个最相似的区域。
  • 将它们合并成一个更大的区域。
  • 重复直到只剩下一个区域。

这就产生了一个依次增大的区域层次结构,正如我们所希望的那样

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Selective search Algorithm to generate regions for object locations

步骤 3: 使用生成的区域产生候选对象位置

现在我们知道了选择性搜索是如何工作的,让我们进入 R-CNN 的细节

R-CNN 将地区提案与 CNN 相结合。

什么是区域提案?

区域建议是检测器可用的候选检测的集合。CNN 在整个图像上运行滑动窗口,但是 R-CNN 只选择几个窗口。R-CNN 对一幅图像使用 2000 个区域。

区域建议运行一种称为分段算法的算法,该算法使用选择性搜索。

但是 R-CNN 中的物体检测是如何工作的呢?

  1. 使用选择性搜索提取大约 2000 个区域提案,生成独立于类别的区域提案。扭曲每一个提议。
  2. 扭曲区域建议被馈送到大型卷积神经 网络。 CNN 作为特征提取器,从每个区域提取固定长度的特征向量。在通过 CNN 之后,R-CNN 为每个区域提议提取 4096 维特征向量
  3. 将 SVM(支持向量机)应用于从 CNN 提取的特征。SVM 有助于对该区域中物体的存在进行分类。回归变量用于预测包围盒的四个值

对图像中的所有得分区域应用贪婪非最大抑制

如果一个区域的交集(IoU)与大于学习阈值的较高得分选定区域重叠,则非最大抑制会拒绝该区域。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

什么是贪婪非 Max 压制,我们为什么要用它?

我们的目标是用一个包围盒检测一个物体一次。但是,使用对象检测,我们可能会发现对相同对象的多次检测。非最大抑制确保只检测一次物体

要了解非最大抑制,我们需要了解 IoU。

并集上的交集— IoU

IoU 通过算法计算两个边界框的并集上的交集,即地面真实的边界框和预测框的边界框

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当 IoU 为 1 时,这意味着预测的和真实的边界框完全重叠。

为了在图像中检测一次对象,非最大抑制会考虑 IoU >为 0.5 的所有边界框

如果我有多个 IoU 大于 0.5 的包围盒怎么办?

非最大抑制

  • 非最大抑制将移除 IoU 小于或等于 0.5 的所有边界框
  • 选取 IoU 值最高的边界框,并抑制其他边界框以识别同一对象

例如,如果我们有三个分别为 0.6、0.7 和 0.9 的矩形。为了让 IoU 识别下图中的车辆,非最大抑制将保留 IoU 为 0.9 的边界框,并将抑制剩余的 IoU 为 0.6 和 0.7 的边界框。

对于下图中的汽车,非最大抑制将保持 IoU 为 0.8,抑制或移除 IoU 边界框为 0.7

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

R-CNN 面临的最大挑战是培训缓慢且昂贵

R-CNN 的体系结构

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

是什么让 R-CNN 的训练又慢又贵?

  • 我们基于选择性搜索为每幅图像提取 2000 个区域。
  • 使用 CNN 提取每个图像区域的特征。对于 N 个图像,我们将有 N*2000 个 CNN 特征。
  • R-CNN 的对象检测使用三种模型:

CNN 用于特征提取

用于识别物体的线性 SVM 分类器

收紧边界框的回归模型

那么我们如何让算法更加高效快速呢?

R-CNN 需要改进的地方很少

  • 使用一个 ConvNet 处理图像一次,而不是对图像的每个区域使用 2000 个 con vnet
  • 使用单一模型提取特征、分类和生成边界框,不像 R-CNN 使用三种不同的模型

这一切都是在快速 R-CNN 中完成的。

快速 R-CNN

快速 R-CNN 是一个快速框架,用于对象分类和具有深度网络的对象检测

快速 R-CNN 的结构和工作原理

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

快速 R-CNN 网络将图像和一组对象提议作为输入。

与 R-CNN 不同,快速 R-CNN 使用单个深度 ConvNet 一次提取整个图像的特征。

我们还使用选择性搜索为图像创建一组 ROI(感兴趣区域)感兴趣区域(RoI)层从特征图中提取一个固定长度的特征向量,用于对象检测。RoI 图层是只有一个金字塔等级的空间金字塔池图层的特例

全连接层(FC)需要固定大小的输入。因此,我们使用 ROI Pooling 层将用于对象检测的特征图的补丁扭曲到固定大小

ROI pooling 层然后被送入 FC 进行分类以及定位。 RoI 池层使用最大池。它将任何感兴趣的有效区域内的要素转换成一个小的要素地图。

全连接层分支成两个同级输出层

  • 一个具有对 K 个对象类的 softmax 概率估计,加上一个包罗万象的“背景”类
  • 另一层带有一个回归器,为 K 个对象类中的每一个输出精确边界框位置的四个实数值。

R-CNN 和快速 R-CNN 的主要区别

  • **快速 R-CNN 使用单一深度 ConvNet 进行特征提取。**与 R-CNN 对图像的每个区域使用 2000 个 ConvNet 不同,单个深度 conv net 大大加快了图像处理的速度。
  • 快速 R-CNN 使用 softmax 进行对象分类,而不是 R-CNN 中使用的 SVM。在异议分类方面,Softmax 略胜 SVM
  • 快速 R-CNN 使用多任务丢失实现深度神经网络的端到端训练,提高了检测精度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

快速 R-CNN 使用选择性搜索作为发现感兴趣区域的建议方法,这是一个缓慢且耗时的过程。不适合大型真实数据集

更快的 R-CNN

更快的 R-CNN 不使用昂贵的选择性搜索而是使用区域建议网络。

这是一个单一、统一的目标检测网络

更快的 R-CNN 由两个阶段组成

  • 第一阶段是提议区域的深度全卷积网络,称为区域提议网络(RPN)。RPN 模块作为统一网络的关注点
  • 第二阶段是快速 R-CNN 检测器,使用 RoIPool 从每个候选框中提取特征,并执行分类和包围盒回归

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Faster R-CNN

区域提案网络

区域提议网络将任意大小的图像作为输入,并输出一组矩形对象提议,每个提议都有一个客观分数。这是通过在卷积层生成的特征图上滑动一个小网络来实现的

RPN 与快速 R-CNN 对象检测网络共享计算。

从 RPN 生成的要素被提供给两个完全连接的同级图层-用于边界框的框回归图层和用于对象分类的框分类图层。

RPN 是高效的,每幅图像处理 10 ms 以生成 ROI。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Region Proposal Network

锚点位于所讨论的滑动窗口的中心,并与比例和纵横比相关联。更快的 R-CNN 使用 3 个比例和 3 个纵横比,在每个滑动窗口产生 9 个锚。

锚点有助于平移不变性。

在每个滑动窗口位置,我们同时预测多个区域建议。每个位置的最大可能建议数表示为 k

Reg 层有 4k 个输出,对 k 个框的坐标进行编码,cls 层输出 2k 个分数,估计每个提议的反对或不反对的概率

快速 R-CNN 的结构和工作原理

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

快速 R-CNN 由 3 个不同的神经网络组成

  1. 使用深度卷积层从输入图像生成特征地图的特征网络
  2. 区域提议网络(RPN)用于识别不同的区域,其对于每个滑动窗口使用 9 个锚。这有助于平移不变性。RPN 生成许多被称为感兴趣区域(ROI)的边界框,这些边界框对于对象的存在具有高概率
  3. 检测网络是 R-CNN,它以来自卷积层和 RPN 网络的输入作为特征映射。这将生成对象的边界框和类

更快的 R-CNN 以图像作为输入,通过特征网络生成特征图。

RPN 使用来自特征网络的特征地图作为输入来生成对象提议的矩形框和对象性分数。

来自 RPN 的预测区域提议随后使用 RoI 池层进行整形。扭曲成固定的向量大小。

然后,扭曲的固定大小向量被馈送到两个完全连接的兄弟层,一个回归层用于预测边界框的偏移值,一个分类层用于对象分类

使用更快的 R-CNN

  • 三维物体检测
  • 基于部件的检测
  • 实例分割
  • 图像字幕

摘要

我们从一个简单的 CNN 开始,它用于图像分类和图像中单个物体的物体检测。

R-CNN 用于图像分类以及图像中多个对象的定位。

R-CNN 又慢又贵,所以快速 R-CNN 被开发成一种更快更有效的算法。R-CNN 和 Fast R-CNN 都使用选择性搜索来搜索图像中的区域。

快速 R-CNN 将 RPN(区域建议网络)与快速 R-CNN 一起用于多图像分类、检测和分割。

在下一篇文章中,我们将探索 YOLO 和面具 R-CNN。

参考文献:

http://vision . Stanford . edu/teaching/cs 231 b _ spring 1415/slides/ssearch _ schuyler . pdf

【https://arxiv.org/pdf/1406.4729.pdf

https://arxiv.org/pdf/1506.01497.pdf

【https://arxiv.org/pdf/1311.2524.pdf 号

http://www . cs . Toronto . edu/~ ting Wu Wang/semantic _ segmentation . pdf

http://www . cs . Toronto . edu/~ ting Wu Wang/semantic _ segmentation . pdf

https://IVI . fnwi . UVA . nl/ISIS/publications/2013/uijlingsijcv 2013/uijlingsijcv 2013 . pdf

http://www . robots . ox . AC . uk/~ tvg/publications/talks/fast-rcnn-slides . pdf

计算机视觉——从 CNN 到面具 R-CNN 和 YOLO 之旅——第二部分

原文:https://towardsdatascience.com/computer-vision-a-journey-from-cnn-to-mask-r-cnn-and-yolo-part-2-b0b9e67762b1?source=collection_archive---------5-----------------------

这是探索和理解 YOLO 建筑和工作方式系列的第二篇文章(你只看一次)。

点击 CNN 上详细了解计算机视觉算法,基于区域的 CNN(R-CNN),快速 R-CNN,更快 R-CNN 。这是第 1 部分。

在下一篇文章中,我们将浏览 YOLO v3 的代码

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

YOLO——你只需看一次就是更好、更快、更准确的计算机视觉算法的答案。

你只需看一次(YOLO)图像,就能预测出哪些物体存在以及它们在哪里。

单个卷积网络同时预测多个边界框和这些框的类别概率。

YOLO 在全图像上训练,直接优化检测性能。这使得 YOLO 非常快速和准确

YOLO 的特色

  • YOLO,一种对象检测算法同时发现图像网格中的所有对象
  • 对完整图像使用单个卷积网络
  • 与滑动窗口或基于区域的技术不同,YOLO 在训练和测试期间看到了整个图像,因此它隐式地编码了关于类及其外观的上下文信息。因此与快速的 R-CNN 相比,产生的背景错误不到一半。
  • **YOLO 使用整个图像的特征来预测每个包围盒。**它还同时预测一幅图像的所有类的所有边界框。预测边界框和这些框的类别概率。
  • 将检测视为回归问题
  • 极其快速准确

YOLO 的工作

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

You Only Look Once-YOLO

  • YOLO 拍摄了一幅图像,并将其分割成一个 SxS 网格。每个网格单元仅预测一个对象
  • 在每个网格上应用图像分类和定位
  • 如果对象的中心落入网格单元,则该网格单元负责检测该对象
  • 每个网格单元预测 B 个边界框,这些框具有置信度得分
  1. **置信度得分反映了模型对盒子包含对象的置信度,以及它认为盒子预测的准确性。如果对象不存在,则置信度得分将为零。**置信度预测表示预测框和任何地面真实框之间的 IOU。Pr(Object)∫IOU 真值 pred——预测框和实际真值之间的交集(IOU)
  2. 当网格单元中出现对象时的边界框
  3. C 类概率

了解 YOLO 的输出

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • pc 定义网格中物体的存在,是概率。当一个物体存在时,它包含概率,当网格中没有物体存在时,它们的 pc 将为零
  • bx,by,bh,bw 指定物体出现时的边界框bx,by 是相对于网格单元边界的盒子中心。bw、bh 是相对于整个图像的宽度和高度
  • **c1、c2、c3 等。代表班级。**维 c 等于类的数量。类别概率取决于包含对象 P(类别|对象)的网格单元。如果网格单元中存在对象,则存在的类的值为 1,其他类的值为 0

输出的维度会是什么?

将图像分成一个 S × S 的网格。

每个网格单元预测 B 个边界框、这些框的置信度和 C 类概率。

每个边界框由 5 个预测组成:bx、by、bw、bh 和置信度

输出维度将 S×S×(B∫(1+4)+C)张量

例如,如果我们将图像划分为 7×7 的网格,每个网格单元预测 2 个边界框,并且我们有 20 个标记类,则输出将是 7×7 ×( 2 * 5+20)= 7×7×30 张量

地面真值包围盒和预测包围盒之间的 IoU 是什么?

并集上的交集— IoU

IoU 通过算法计算两个边界框的并集上的交集,即地面真实的边界框和预测框的边界框

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当 IoU 为 1 时,这将意味着预测的和真实边界框完全重叠。

为了在图像中检测一次对象,非最大抑制会考虑 IoU >为 0.5 的所有边界框

如果我有多个 IoU 大于 0.5 的包围盒怎么办?

非最大抑制

  • 非最大抑制将移除 IoU 小于或等于 0.5 的所有边界框
  • 选择 IoU 值最高的边界框,并抑制其他边界框,以识别同一物体

例如,如果我们有三个分别为 0.6、0.7 和 0.9 的矩形。为了让 IoU 识别下图中的车辆,非最大抑制将保留 IoU 为 0.9 的边界框,并将抑制剩余的 IoU 为 0.6 和 0.7 的边界框。

对于下图中的汽车,非最大抑制将保持 IoU 为 0.8,抑制或移除 IoU 边界框为 0.7

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

YOLO v1 网络设计

YOLO 的网络架构受 GoogLeNet 图像分类模型的启发

YOLO 的检测网络有 24 个卷积层,后面是 2 个全连接层。

YOLO 使用 1 × 1 缩减层,然后是 3 × 3 卷积层,而不是谷歌网络使用的初始网络

交替的 1 × 1 卷积层减少了来自前面层的特征空间。

在 ImageNet 分类任务中,卷积层以一半的分辨率(224 × 224 输入图像)进行预训练,然后以两倍的分辨率进行检测

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

YOLO 对最后一层使用线性激活函数,对所有其他层使用泄漏 ReLU。

YOLO 使用卷积特征提取器顶部的全连接层直接预测边界框的坐标。YOLO 只预测每张图片有 98 个盒子。

YOLO 的优势

  • 与基于分类器的方法不同,YOLO 在测试时速度极快,因为它只需要一次网络评估
  • 同时执行特征提取、边界框预测、非最大值抑制和上下文推理。
  • YOLO 网络在线训练特征,并针对检测任务优化它们。统一架构带来更快、更准确的模型

YOLO 的局限性

  • YOLO 对边界框预测施加了很强的空间约束,因为每个网格单元只能预测两个框,并且只能有一个类,这限制了模型可以预测的附近对象的数量。
  • YOLO 与成群出现的小物体搏斗,比如一群鸟
  • 努力推广到新的或不寻常的长宽比或配置的对象

YOLO 的其他变体

快速 YOLO

快速 YOLO 是 YOLO 的快速变体。它使用 9 个卷积层,而不是 YOLO 使用的 24 个卷积层,并且还使用发烧过滤器。

YOLO 和快速 YOLO 之间的网络规模不同,但 YOLO 和快速 YOLO 之间的所有培训和测试参数都相同。

我们网络的最终输出是预测的 7 × 7 × 30 张量。

YOLOv2 或 YOLO9000

  • yolov 2 中的输入尺寸从 224224 增加到 448448 。图像输入大小的增加改善了 mAP(平均精度)
  • YOLOv2 将整个图像划分成 13×13 的网格。这有助于解决 YOLO v1 中较小物体探测的问题
  • YOLOv2 使用批处理规范化,这导致收敛的显著改善,并消除了对其他形式的正则化的需要。我们也可以在不过度拟合的情况下从模型中删除掉的部分。
  • YOLOv2 在边界框的维度上运行 k-means 聚类,以获得模型的良好先验或锚。YOLOv2 发现 k= 5 给出了召回率与模型复杂性之间的良好权衡。YOLOv2 使用 5 个锚盒
  • YOLOv2 使用 Darknet 架构,具有 19 个卷积层、5 个最大池层和一个用于分类对象的 softmax 层
  • YOLOv2 使用定位框来预测边界框。

什么是锚盒或先验,它有什么帮助?

锚盒或先验

锚定框用于检测多个对象、不同比例的对象以及重叠的对象。这提高了目标检测的速度和效率。

锚定框一次评估所有对象预测,消除了使用滑动窗口扫描图像的需要

锚点是一组具有一定高度和宽度的预定义边界框。定义这些框是为了捕捉要检测的特定对象类的比例和纵横比。

YOLOv2 将整个图像划分为 13 X 13 个网格单元。 YOLOv2 在边界框的维度上运行 k-means 聚类,以获得模型的良好先验或锚。YOLOv2 发现 k= 5 给出更好的性能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Red is Ground Truth. Blue boxes are 5 Anchor boxes

为了预测一张图片中的多个对象,YOLOv2 进行了数千次预测。最终的目标检测是通过去除属于背景类的锚框来完成的,剩余的锚框通过它们的置信度得分来过滤。我们发现 IoU 大于 0.5 的锚盒。使用前面解释的非最大抑制来选择具有最大置信度得分的锚框。

YOLOv3

  • 使用 9 个锚
  • 使用逻辑回归来预测客观性分数,而不是 YOLO v2 中使用的 Softmax 函数
  • YOLO v3 使用 Darknet-53 网络作为具有 53 个卷积层的特征提取器

YOLO v3 的代码将在下一篇文章中出现

参考资料:

https://pjreddie.com/media/files/papers/yolo.pdf

https://arxiv.org/pdf/1612.08242.pdf

https://pjreddie.com/media/files/papers/YOLOv3.pdf

http://deeplearning.csail.mit.edu/instance_ross.pdf

计算机视觉——导论

原文:https://towardsdatascience.com/computer-vision-an-introduction-bbc81743a2f7?source=collection_archive---------4-----------------------

揭开像素背后的含义

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

之前的博客 中,我讨论了视觉感知及其生物和计算两个方面。这个博客专门讨论计算视觉,也称为计算机视觉。

什么是计算机视觉?

计算机视觉已经存在了 50 多年,但最近,我们看到人们对机器如何“看”以及计算机视觉如何用于为消费者和企业制造产品的兴趣再次高涨。这类应用的几个例子是——Amazon Go、Google Lens、自动驾驶汽车、人脸识别。

所有这些背后的关键驱动因素是计算机视觉。最简单地说,计算机视觉是人工智能广泛领域下的一门学科,它教会机器看东西。它的目标是从像素中提取意义。

从生物科学的角度来看,它的目标是提出人类视觉系统的计算模型。从工程的角度来看,计算机视觉旨在建立自主系统,这些系统可以执行人类视觉系统可以执行的一些任务(甚至在许多情况下超越人类视觉系统)。

简史

1966 年夏天,麻省理工学院人工智能小组的西蒙·派珀特和马文·明斯基启动了一个名为夏季视觉项目的项目。该项目的目的是建立一个可以分析场景和识别场景中的对象的系统。因此,研究人员和科技巨头仍在试图解码的巨大而令人困惑的计算机视觉领域,最初被人工智能的先驱们认为对于一个本科生暑期项目来说足够简单。

在 70 年代,麻省理工学院的神经科学家大卫·马尔(David Marr)从人类感知的小脑、海马体和皮层的研究中汲取灵感,为现代计算机视觉建立了基础,因此被称为现代计算机视觉之父。他的大部分思想都集中在名为《愿景》的主要著作中。

深度视觉

深度学习从 2012 年开始兴起。深度学习是机器学习的一个子集,其中人工神经网络,受人脑启发的算法,从大量数据中学习。为推荐系统提供动力,识别和标记照片中的朋友,将你的声音翻译成文本,将文本翻译成不同的语言,深度学习已经改变了计算机视觉,使其走向卓越的性能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image classification error rate over time, drastic drop after the introduction of deep learning. source — tractable.ai

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这些基于深度学习的计算机视觉算法,如卷积神经网络,已经开始给出有希望的结果,具有卓越的精度,甚至在某些任务上超过人类水平的精度。

应用程序

**智能手机:**二维码、计算摄影(安卓镜头虚化、iPhone 人像模式)、全景构建(谷歌照片球体)、人脸检测、表情检测(微笑)、Snapchat 滤镜(人脸追踪)、谷歌镜头、夜视(像素)

Web: 图片搜索、谷歌照片(人脸识别、物体识别、场景识别、视觉地理定位)、脸书(图片字幕)、谷歌地图航拍成像(图片拼接)、YouTube(内容分类)

VR/AR: 由外向内跟踪(HTC VIVE)、由内向外跟踪(同步定位和映射,HoloLens)、对象遮挡(密集深度估计)

医学影像: CAT / MRI 重建、辅助诊断、自动病理、连接组学、AI 引导手术

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

http://www.ai.mit.edu/projects/medical-vision/surgery/surgical_navigation.html

**媒体:**电影、电视的视觉效果(重建)、虚拟体育回放(重建)、基于语义的自动编辑(重建、识别)

**保险:**理赔自动化、损失分析、财产检查

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

source — Roadzen

关于工业中计算机视觉应用的详尽列表,请参见由谷歌高级研究科学家大卫·劳维护的页面。

挑战

即使在大量的工作发表后,计算机视觉仍未解决。它只在很少的约束条件下工作。这种困难的一个主要原因是人类视觉系统对于许多任务来说太好了,例如人脸识别。人类可以在光照、视角、表情等各种变化下识别人脸。这是计算机在这种情况下所遭受的。

隐私和道德 —在使用监控时,保险业的尖端技术包括通过监控驾驶行为来调整保费和保单,但另一方面,视觉监控系统对隐私和道德造成了巨大风险。举个例子,我们看中国,用面部识别追踪少数民族。最近,旧金山成为美国第一个禁止政府使用面部识别的城市。

缺乏可解释性 —基于现代神经网络的算法在某种程度上仍然是一个黑箱。因此,当一个模型将一幅图像归类为一辆汽车时,我们实际上并不知道是什么导致它这样做。可解释性是几个领域的关键要求,比如保险和自动驾驶,这些领域目前在这些算法中缺失。

https://www . economist . com/science-and-technology/2018/02/15/for-artificial-intelligence-to-thrive-it-must-explain-self

https://www . DARPA . mil/program/explable-artificial-intelligence

Deep Fakes —一方面,解决基于深度学习的视觉正在解决许多现实世界的问题,但另一方面,它也产生了一些问题。使用深度学习技术,现在任何拥有强大 GPU 和训练数据的人都可以用 DeepFakes 创建可信的假图像或视频。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个问题非常危险,以至于五角大楼通过国防高级研究计划局(DARPA)正在与该国几个最大的研究机构合作,以解决 DeepFakes 问题。

对抗性攻击对抗性示例是攻击者有意设计的机器学习模型的输入,以使模型出错;它们就像机器的视错觉。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Computer vision model fails to recognize a person when a patch of paper is attached to him

计算机视觉的未来

根据一份报告,2017 年计算机视觉市场价值为 23.7 亿美元,预计到 2023 年将达到 253.2 亿美元,CAGR 为 47.54%。

世界正在经历一场深刻的数字化转型,尤其是没有放缓迹象的印度。仅 Jio 每月平均数据消耗就达 10.8 GB。根据这份报告,每分钟——

  • 用户观看了 414.66 万个 YouTube 视频
  • Instagram 用户发布了 46740 张照片
  • Snapchat 用户分享了 527,760 张照片

这些都给计算机视觉提供了大量的机会去寻找模式并理解它。

即使有了这些迷人的发展,人工智能和计算机视觉领域仍然需要解决目前与之相关的问题,如偏见、风险意识和缺乏可解释性。为了解决这些问题,像平安这样的公司已经开始采取小步骤,利用符号人工智能(人工智能的一种早期形式)到现代人工智能算法中,以给出其决策的可解释性,但仍有一段路要走。

计算机视觉—手写数学答题卡的自动评分

原文:https://towardsdatascience.com/computer-vision-auto-grading-handwritten-mathematical-answersheets-8974744f72dd?source=collection_archive---------12-----------------------

使用 python 自动校正和评分数学工作表的计算机视觉模型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Jeswin Thomas on Unsplash

阅读是教育的一个重要部分。手动评估每份答卷,提供公平、公正和有效的分数在大多数情况下是困难的。这篇文章是关于我和我的导师比乔恩·古哈的实习项目,建立一个计算机视觉模型,它将自动评估答案纸,从而确保分数完全基于学生的表现。

概观

下面是我们将要检查和评分的样本工作表。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Sample Worksheets

每张工作表都是由不同的人写的。线宽、同页字体、笔尖宽度、字符间距等都会有变化。

这个想法是纠正工作表中的每一行,并用方框标记这些行。其中绿框表示线正确,红框表示线不正确。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Sample Output

(注意:我没有在这里添加所有代码,如果你想检查你可以访问我的 GitHub 在那里我有一个 ipynb 笔记本的教程)

工作流程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Workflow diagram

工作流程中有两个模块工作空间检测模块分析模块。工作空间检测模块负责检测给定纸张中的多个工作空间。

分析模块负责在任何给定的单个工作空间中检测和定位行中的字符,并对它们进行数学分析,然后根据它们的正确性绘制红、绿框。

工作空间检测

工作空间检测模块假设在给定的扫描工作表中存在有效的矩形框。下图显示了工作表设计。工作表中三个最大的矩形框是工作空间。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Worsheet design

工作空间检测模块使用 openCV 完成。我们将首先找到矩形框,然后根据它们在工作表中的位置对它们进行排序。由于工作表中有许多矩形,我们必须从其他矩形中选择有效的工作空间。让我们看看每个步骤是如何完成的

步骤 1:寻找矩形框

矩形由两条水平线和垂直线组成。所以第一步是找出所有的水平线和垂直线,忽略数字、符号或任何写在工作表上的东西。

下面的代码将首先创建一个名为 “vertical_lines_img” 的二进制图像,它包含工作表中出现的所有垂直线,然后创建另一个名为" horizontal_lines_img" 的二进制图像*,它包含工作表中出现的所有水平线。*

接下来,我们要将图像*“垂直 _ 线条 _img”与“水平 _ 线条 _ img”*相加,得到最终的图像。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Adding vertical and horizontal line

轮廓定义为沿着图像边界连接具有相同强度的所有点的线。

OpenCV 具有 findContour()函数,帮助从图像中提取轮廓。每个单独的轮廓是对象边界点的(x,y)坐标的 Numpy 数组。我们可以用它来找到最终图像中的所有对象(最终图像中只有对象是矩形)。

因为最终图像只是原始图像的二进制版本,所以最终图像中矩形的坐标等于原始图像中矩形的坐标。

现在我们知道了坐标,让我们使用 openCV 的*draw contours()函数在原始图像上绘制它们。*

Code to find and draw the contours

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

步骤 2:对轮廓进行排序

现在我们已经找到了所有的矩形,是时候根据它们的坐标从上到下对它们进行排序了。下面的代码会帮我们做到这一点。

Function to sort contours Code Reference

Sorted contours

sort_contours 函数将返回按照我们给出的方法排序的轮廓和边界框(左上和右下坐标)。在这种情况下,方法是从上到下。

步骤 3:基于区域的选择

有许多矩形,但我们只需要三个最大的。如何选择三个最大的矩形?….一个答案是找出矩形的面积,然后选择面积最大的前 3 个矩形。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Overall solution

这些选定的矩形是工作空间,然后从工作表中提取出来,并发送到分析模块。

分析模块

如上所述的分析模块将首先检测行,预测每行中的字符,最后用预测的字符形成方程,然后通过标记框来评估它们。

线检测

检测这些线是棘手的部分,每个人都有自己解决方程的方法,有些人一步一步地解决,有些人只用一行就能解决,有些人可能写了好几页的步骤,有些人写了远离方程的指数,使模块混淆,将这些指数作为一个单独的行。

我们的线检测模块假设线之间有足够的间隙,并且在指数字符和线之间有一些交集。首先,检测到的工作空间被转换成二进制图像,然后压缩成一个单一的阵列,以采取向前的导数。哪里有线,哪里的导数就有变化。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Change in derivatives of a binary image

上面的代码只是线条提取工作原理的一瞥。要查看完整的代码,请点击***。*****

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

字符分割和指数检测

检测完所有线条后,我们必须将提取的线条图像发送到text _ segment函数,该函数将使用 openCV 的 find contours 来分割字符,并使用上述函数 sort_contours 对字符进行排序,其中方法现在设置为从左到右。

对我们来说,判断给定的数是否是指数很容易,但对模型来说就没那么容易了。假设指数至少在直线的一半以上,我们可以在图像的中心画一条基线,基线以上的任何字符都被认为是指数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Exponential detection

光学字符识别

我们可以使用 MNIST 数据集用于数字(2828 像素)和 Kaggle 的手写数学符号数据集用于符号(4545 像素)来训练模型。**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

MNIST IMAGES

MNIST 实际上是如何形成的?

  1. 从 500 个不同的作者那里收集的 128 * 128 像素的手写数字。
  2. 高斯滤波器被应用于图像以柔化边缘
  3. 然后,通过保持长宽比,将数字放置在正方形图像的中央。
  4. 然后,使用双三次插值将图像下采样至 28 × 28 像素

在训练之前,符号的图像以与 MNIST 数字相同的方式进行预处理。预处理的原因是我们选择的两个数据集具有不同的特征,如尺寸、厚度和线宽,这使得深度学习模型很难找到模式。预处理帮助我们减少数字和符号之间的差异。

深度柱状卷积神经网络(DCCNN) 上训练了近 60,000 幅数字和预处理符号的图像,这是一种单一的深度和广度神经网络架构,在各种图像分类挑战(如 MNIST、CIFAR-10 和 CIFAR-100 数据集)上提供接近最先进的性能,如集成模型。这个模型达到了 96 %的准确率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Deep Columnar Convolutional Architecture (DCCNN)

点击 查看训练代码 DCCNN_training.ipynb

评估和绘图框

评估是最后也是最重要的部分。为了求解任何方程,我们可以使用 python 的 eval 方法。

eva 方法解析传递给它的表达式,并在程序中运行 python 表达式(代码)

这是一个关于 eval 如何工作的例子

****>>Enter the function y(in terms of x):‘x*(x+1)*(x+2)’>>Enter the value of x:3>>print(y)60****

评估 流程涉及的步骤有:

  1. 解决给定的数学问题并保存答案
  2. 求解每一个手写行,并将其导出值与存储的答案进行比较。
  3. 如果线条正确,画一个绿色的边界框,如果线条错误,画一个红色的边界框。

我们举个例子,说问题是解方程 Ax + By**

其中,A=56,B=7,x=3,y=13,这个等式的答案是 595 (563 +713 = 595)。**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Sample workspace

绿色方框表示这条线是正确的,而红色方框表示这条线是错误的。

第一行和最后一行是正确的,通过求解这些行,我们得到 595,这与实际答案相符。

第二行(567 + 92)错了。3 是 9,但它被写成 7,在求解时我们得到 584,这不等于 595*

第三行(595 + 92)也是错误的,在求解这一行时,我们得到 684,它也不等于 595。

结论

总而言之,扫描的工作表被发送到工作空间检测模块,它将返回给定工作表中的所有矩形工作空间,然后检测到的工作空间被传递到线提取模块以提取所有的线。提取的线然后被发送到字符分割模块,它将分割字符,深度学习模型 DCCNN 将预测数字/符号。最后,评估模块将评估线,并绘制红/绿包围盒。

自动化评分过程不仅有助于教师,也为学生创造了舒适的学习体验。通过识别更复杂的数学方程,如微分积分方程、识别字符未分离的草书笔迹、检测剽窃和识别化学方程,该解决方案可以变得更酷。

感谢阅读到最后!!…如果你喜欢这篇文章,请鼓掌让我知道,如果你能通过与你的朋友分享来帮助它传播,我将非常感激:)。✌️

计算机视觉——利用哈尔级联分类器检测物体

原文:https://towardsdatascience.com/computer-vision-detecting-objects-using-haar-cascade-classifier-4585472829a9?source=collection_archive---------0-----------------------

在开始进入细节之前,我们先来了解一下什么是计算机视觉以及它的一些应用。

什么是计算机视觉?

计算机视觉是一个研究领域,包括计算机如何看到和理解数字图像和视频。

计算机视觉包括看到或感知视觉刺激,理解所看到的内容,并提取可用于其他机器学习活动的复杂信息。

计算机视觉的应用

计算机视觉有许多实际应用:

  • 自动驾驶汽车 —这是计算机视觉最重要的应用之一,自动驾驶汽车需要收集周围的信息,以决定如何行动。
  • 面部识别— 这也是计算机视觉的一个非常重要的应用,电子设备使用面部识别技术来验证用户的身份。
  • 图像搜索和物体识别 —现在我们可以使用图像搜索在图像中搜索物体。一个很好的例子是谷歌镜头,我们可以通过点击图像的照片来搜索图像中的特定对象,计算机视觉算法将搜索图像目录,并从图像中提取信息。
  • 机器人 —大多数机器人机器,通常在制造业中,需要看到它们的周围环境来执行手头的任务。在制造业中,机器可以通过“观察”来检查装配公差。

既然我们知道了计算机视觉的含义和它的一些应用,让我们深入研究它的实现。为了实现计算机视觉的各种例子,我们将使用 OpenCV 库。

OpenCV (开源计算机视觉库:http://opencv.org)是一个开源的 BSD 许可库,包括数百种计算机视觉算法。

**Haar 级联分类器:**我们将使用 Haar 级联分类器来实现我们的用例。Haar 级联分类器是一种有效的目标检测方法,由 Paul Viola 和 Michael Jones 于 2001 年在他们的论文“使用简单特征的增强级联的快速目标检测”中提出。

那么,让我们试着理解这些哈尔级联分类器是什么。这基本上是一种基于机器学习的方法,其中从大量正面和负面图像中训练级联函数。基于该训练,然后使用它来检测其他图像中的对象。

所以这是如何工作的,他们是巨大的个体。具有许多特性集的 xml 文件,每个 xml 对应于一个非常特定的用例类型。

例如,如果你去 haarcascade 的 github 页面,你会看到有一个特定的 xml 文件,其中包含检测全身下体眼睛正面等等的特征集。

为了理解 haar 级联分类器如何工作,以及它将如何用于计算机视觉,让我们实现一些用例。

1。面部检测

在这个用例中,我们将尝试使用Haar cascade _ front alface _ default . XML来检测个人的面部

我们在这里使用的图像尺寸相当大,所以为了更好的输出,我们缩小了图像尺寸。

我们使用下面的代码来调整图像的大小:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第一步

现在我们已经调整了图像的大小,让我们继续导入 cv2numpy 并使用 OpenCV 的 CascadeClassifier 函数指向我们存储 XML 文件的位置,在我们的例子中是Haar cascade _ frontal face _ default . XML。我已经将 xml 文件下载到我的本地,并使用了我的机器的路径,但是如果你愿意,你可以直接将它指向 github 的位置。

import cv2
import numpy as npface_classifier = cv2.CascadeClassifier('/haarcascade_frontalface_default.xml')

第二步

现在第二步是加载图像并将其转换成灰度。在展示代码之前,我想告诉你我们在这里将图像转换为灰度的原因。

通常我们看到的图像是 RGB 通道(红、绿、蓝)的形式。因此,当 OpenCV 读取 RGB 图像时,它通常将图像存储在 BGR(蓝、绿、红)通道中。为了图像识别的目的,我们需要将 BGR 通道转换成灰色通道。这是因为灰色通道易于处理,并且计算量较小,因为它只包含 1 个黑白通道。

gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)

这里,函数 cvtColor 的参数将是图像变量名(调整大小)和 COLOR_BGR2GRAY。

第三步

现在,在将图像从 RGB 转换为灰度后,我们现在将尝试定位我们面部的确切特征。让我们看看如何用代码实现它。

faces = face_classifier.detectMultiScale(gray, 1.0485258, 6)

在这段代码中,我们要做的是,使用 face_classifier ,它是一个加载了Haar cascode _ frontal face _ default的对象。 **xml,**我们使用了一个内置的函数,叫做 detectMultiScale。

该功能将帮助我们找到新图像的特征/位置。其方式是,它将使用来自 face_classifier 对象的所有特征来检测新图像的特征。

我们将传递给该函数的参数是:

  1. 灰度变量—在我们的例子中是灰色
  2. 比例因子 —指定图像尺寸在每个图像比例下缩小多少的参数
    。基本上,比例因子用于创建您的比例金字塔。更多的解释是,您的模型在训练期间定义了一个固定的大小,这在 XML 中是可见的。这意味着如果存在的话,在图像中检测到脸部的这个尺寸。但是,通过重新调整输入图像的比例,您可以将较大的人脸调整为较小的人脸,从而使算法可以检测到它。1.05 是一个很好的可能值,这意味着您使用一个小步骤来调整大小,即减少 5%的大小,您增加了找到与检测模型匹配的大小的机会。这也意味着该算法工作较慢,因为它更彻底。为了更快地检测,您可以将它增加到 1.4,但有可能会完全错过一些面孔。在我们的例子中,我使用 1.0485258 作为比例因子,因为这对我正在使用的图像来说是完美的。
  3. 最小邻居 —指定每个候选矩形应该有多少邻居来保留它的参数。该参数将影响检测到的人脸的质量。值越高,检测次数越少,但质量越高。3~6 是一个很好的值。在我们的例子中,我选择了 6 作为我的邻居,这对于我使用的图片来说是完美的。

第四步

从上面的步骤中,函数 detectMultiScale 返回 4 个值——检测到的面部特征的 x 坐标、y 坐标、宽度(w)和高度(h)。基于这 4 个值,我们将在脸部周围画一个矩形。

if faces is ():
    print("No faces found")
for (x,y,w,h) in faces:
    cv2.rectangle(resized, (x,y), (x+w,y+h), (127,0,255), 2)
    cv2.imshow('Face Detection', resized)
    cv2.waitKey(0)

cv2.destroyAllWindows()

将所有 4 个步骤整合在一起,下面是代码:

import cv2
import numpy as npface_classifier = cv2.CascadeClassifier('/haarcascade_frontalface_default.xml')gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)''' Our classifier returns the ROI of the detected face as a tuple, 
It stores the top left coordinate and the bottom right coordiantes'''faces = face_classifier.detectMultiScale(gray, 1.0485258, 6)'''When no faces detected, face_classifier returns and empty tuple'''
if faces is ():
    print("No faces found")'''We iterate through our faces array and draw a rectangle over each face in faces'''
for (x,y,w,h) in faces:
    cv2.rectangle(resized, (x,y), (x+w,y+h), (127,0,255), 2)
    cv2.imshow('Face Detection', resized)
    cv2.waitKey(0)

cv2.destroyAllWindows()

我已经创建了上述程序的输出作为一个视频,并将其嵌入下面。如果你看到,程序不能正确地检测到一些面孔。原因是为了使 haarcascade 分类器正常工作,人脸应该是适当可见的。在输出中没有被检测到的那个有点不清楚。

尽管如此,我将在未来的帖子中尝试改进这一点,我们将使用不同类型的涉及深度学习的算法来减轻这一点。

Face detection using haar cascade classifier

2.人脸和眼睛检测

现在我们已经对人脸检测的工作原理有了一些了解,让我们看看如何检测人脸和眼睛

在这个实现中,与人脸检测代码相比,我们做了一些改动。

第一步

为了检测眼睛,我们还导入了 haarcascade_eye.xml 文件。

eye_classifier = cv2.CascadeClassifier('/haarcascade_eye.xml')

第二步

一旦我们使用 detectMultiScale 函数获得人脸检测特征的 x 坐标、y 坐标、宽度(w)和高度(h ),我们将创建 2 个 numpy 数组— roi_grayroi_color。****ROI _ gray是使用变量“gray”创建的 numpy 数组。我们创建它的原因是在提取眼睛的特征(例如,ey,ew,eh)时,将这个灰色通道版本传递给 detectMultiScale 函数。

for (x,y,w,h) in faces:
    cv2.rectangle(img,(x,y),(x+w,y+h),(127,0,255),2)
    cv2.imshow('img',img)
    cv2.waitKey(0)
    roi_gray = gray[y:y+h, x:x+w]
    roi_color = img[y:y+h, x:x+w]
    eyes = eye_classifier.detectMultiScale(roi_gray)

第三步

一旦我们提取了眼睛的特征(例如,ey,ew,eh ),我们将遍历它们并通过传递 numpy 数组 **roi_color 创建一个矩形。**传递 roi_color 而不传递 roi_gray 的原因是 roi_color 是实际 RGB 比例图像的数组,而 roi_gray 是图像的灰度,我们在代码中使用它来加快处理速度,同时提取图像的尺寸/坐标,然后使用这些尺寸将它传递到原始数组中,在我们的示例中是 roi_color

for (ex,ey,ew,eh) in eyes:
        cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(255,255,0),2)

将所有步骤整合在一起:

import numpy as np
import cv2

face_classifier = cv2.CascadeClassifier('/haarcascade_frontalface_default.xml')
eye_classifier = cv2.CascadeClassifier('/haarcascade_eye.xml')img = cv2.imread('/group.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)faces = face_classifier.detectMultiScale(gray, 1.05, 3)# When no faces detected, face_classifier returns and empty tuple
if faces is ():
    print("No Face Found")for (x,y,w,h) in faces:
    cv2.rectangle(img,(x,y),(x+w,y+h),(127,0,255),2)
    cv2.imshow('img',img)
    cv2.waitKey(0)
    roi_gray = gray[y:y+h, x:x+w]
    roi_color = img[y:y+h, x:x+w]
    eyes = eye_classifier.detectMultiScale(roi_gray)
    for (ex,ey,ew,eh) in eyes:
        cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(255,255,0),2)
        cv2.imshow('img',img)
        cv2.waitKey(0)

cv2.destroyAllWindows()

我已经创建了上述程序的输出作为一个视频,并将其嵌入下面。如果你看到程序不能正确检测戴眼镜的人的眼睛。也许我们需要一个更复杂的算法。

Face and Eye detection using haar cascade classifier

3.流式视频中的车辆检测

让我们再实现一个 haar 级联分类器的用例。在这个用例中,我们将从流视频中检测车辆。我实现了这些用例来展示它是如何工作的。对于这个分类器,还有很多其他的 XML,你可以用来实现其他一些计算机视觉的例子。这是 xmls 的 github 链接。

这里的实现与我们为人脸检测所做的一样,所以我不会详细解释整个过程。然而,代码中有一些变化。

第一步

为了检测车辆的特征,我们需要导入 haarcascade_car.xml.

使用 cv2 的视频捕捉并将值存储在 cap

从一个VideoCapture中读取(cap.read())返回一个元组(ret, frame)。对于第一项,您检查读取是否成功,如果成功,则继续使用返回的frame.

cap = cv2.VideoCapture('/vehicle.mp4')# Loop once video is successfully loaded
while cap.isOpened():

    time.sleep(.05)
    # Read first frame
    ret, frame = cap.read()

第二步

现在我们有了(ret, frame)的元组,我们将把 BGR 通道图像转换成灰色通道。出于同样的原因,我们将图像转换为灰度,并使用分类器函数 detectMultiScale 来提取 x 坐标、y 坐标、宽度(w)和高度(h),灰度用于更好的性能吞吐量。

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Pass frame to our car classifier
    cars = car_classifier.detectMultiScale(gray, 1.1, 2)

第三步

基于提取的汽车特征/尺寸,我们将遍历它们,并在图像的每一帧周围绘制一个矩形。

for (x,y,w,h) in cars:
        cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 255), 2)

下面是这方面的综合代码:

import time
import numpy as np
import cv2# Create our body classifier
car_classifier = cv2.CascadeClassifier('\haarcascade_car.xml')# Initiate video capture for video file
cap = cv2.VideoCapture('/vehicle.mp4')# Loop once video is successfully loaded
while cap.isOpened():

    time.sleep(.05)
    # Read first frame
    ret, frame = cap.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Pass frame to our car classifier
    cars = car_classifier.detectMultiScale(gray, 1.1, 2)

    # Extract bounding boxes for any bodies identified
    for (x,y,w,h) in cars:
        cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 255), 2)
        cv2.imshow('Cars', frame)if cv2.waitKey(1) == 13: #13 is the Enter Key
        breakcap.release()
cv2.destroyAllWindows()

现在我们有了完整的代码,让我们检查它的输出。

Car detection using haar cascade classifier

4.流式视频中的行人检测

实现与车辆检测完全相同。这里唯一的不同是,我们将使用 haarcascade_fullbody.xml 来识别行人身体的特征。

下面是它的代码:

import numpy as np
import cv2# Create our body classifier
body_classifier = cv2.CascadeClassifier('\haarcascade_fullbody.xml')# Initiate video capture for video file
cap = cv2.VideoCapture('/moskva.mov')# Loop once video is successfully loaded
while cap.isOpened():

    # Read first frame
    ret, frame = cap.read()gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # Pass frame to our body classifier
    bodies = body_classifier.detectMultiScale(gray, 1.1, 3)

    # Extract bounding boxes for any bodies identified
    for (x,y,w,h) in bodies:
        cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 255), 2)
        cv2.imshow('Pedestrians', frame)if cv2.waitKey(1) == 13: #13 is the Enter Key
        breakcap.release()
cv2.destroyAllWindows()

让我们看看下面视频中的输出是什么样的:

Pedestrians detection using haar cascade classifier.

离别的思绪

尽管 haarcascade 分类器非常有用,但这种方法也有一些缺点。

  1. 其中最具挑战性的部分是精确指定检测多尺度函数的比例因子最小邻居的参数值。我们经常会遇到需要逐个图像地调整这两个参数的情况,对于图像检测用例来说,这是一个很大的障碍。
  2. 比例因子主要用于控制图像金字塔,进而用于在图像的不同比例下检测物体。如果比例因子太大,那么图像检测可能会不准确,我们将会错过处于金字塔层之间比例的对象。
  3. 然而,如果我们降低比例因子的值,那么你将在相同的图像比例上得到许多层金字塔,这使得检测更慢并增加假阳性。

请继续关注即将发布的帖子,在那里我们将看到使用一些复杂的深度学习算法以更有效的方式检测图像的其他酷方法。

还有,如果你想了解 devops,可以参考这个网站。

参考资料:

  1. https://docs . opencv . org/3.4/db/d28/tutorial _ cascade _ classifier . html
  2. https://www . pyimagesearch . com/2016/06/20/detecting-cats-in-images-with-opencv/
  3. https://github.com/krishnaik06/Computer-Vision-Tutorial

初学者的计算机视觉:第 1 部分

原文:https://towardsdatascience.com/computer-vision-for-beginners-part-1-7cca775f58ef?source=collection_archive---------1-----------------------

OpenCV 和 Python 中的图像处理简介

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

计算机视觉是人工智能领域最热门的话题之一。它在自动驾驶汽车、机器人以及各种照片校正应用程序方面取得了巨大进步。目标检测每天都在稳步前进。GANs 也是研究人员目前关注的一个问题。视觉正在向我们展示技术的未来,我们甚至无法想象它的可能性的尽头会是什么。

那么,你想迈出计算机视觉的第一步,并参与到这一最新的运动中来吗?欢迎你来对地方了。从这篇文章中,我们将有一系列的图像处理和物体检测的基础教程。这是 OpenCV 初学者教程的第一部分,完整系列如下:

  1. 理解颜色模型并在图像上绘制图形
  2. 带滤波的图像处理基础知识
  3. 从特征检测到人脸检测
  4. 轮廓检测和享受一点乐趣

本系列的第一个故事将是关于安装 OpenCV,解释颜色模型和在图像上绘制图形。本教程的完整代码也可以在 Github 上找到。现在让我们开始吧。

OpenCV 简介

图像处理 是对图像进行一些操作,以获得想要的操作。想想当我们开始新的数据分析时,我们会做些什么。我们做一些数据预处理和特征工程。图像处理也是一样。我们通过图像处理来处理图片,从中提取有用的信息。我们可以减少噪音,控制亮度和色彩对比度。要了解详细的图像处理基础知识,请访问本视频

OpenCV 代表 开源计算机视觉 库,由英特尔于 1999 年发明。它最初是用 C/C++编写的,所以你可能会看到更多的 C 语言教程,而不是 Python。但是现在它也在 Python 中被广泛用于计算机视觉。首先,让我们为使用 OpenCV 建立一个合适的环境。安装可以按如下方式进行,但您也可以在此处 找到详细描述

pip install opencv-python==3.4.2
pip install opencv-contrib-python==3.3.1

完成安装后,尝试导入软件包,看看它是否工作正常。如果你得到的回报没有任何错误,那么你现在就可以开始了!

import cv2
cv2.__version__

我们要用 OpenCV 做的第一步是导入一个图像,可以这样做。

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline# Import the image
img = cv2.imread('burano.jpg')
plt.imshow(img)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你去过布拉诺吗?它是意大利最美丽的岛屿之一。如果你还没有去过那里,你一定要在下一个假期去看看这个地方。但是如果你已经知道这个岛,你可能会注意到这张照片有些不同。和我们平时看到的布拉诺的图片有点不一样。应该比这更让人欣喜吧!

这是因为 OpenCV 中颜色模式的默认设置是按照 BGR 的顺序来的,这与 Matplotlib 不同。因此,要查看 RGB 模式下的图像,我们需要将其从 BGR 转换为 RGB,如下所示。

# Convert the image into RGB
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img_rgb)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,这是布拉诺!意大利如此可爱的岛屿!

不仅仅是 RGB

让我们再多谈一点颜色模式。 色彩模型是一个使用原色创建全范围色彩的系统。这里有两种不同的颜色模型: 加色模型减色模型 。加色模型使用光在计算机屏幕上表现颜色,而减色模型使用墨水在纸上打印这些数字图像。对于前者,原色是红色、绿色和蓝色(RGB ),对于后者,原色是青色、品红色、黄色和黑色(CMYK)。我们在图像上看到的所有其他颜色都是由这些原色组合或混合而成的。因此,当图片以 RGB 和 CMYK 表示时,它们的描述会有所不同。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(Source)

你会很习惯这两种模型。然而,在颜色模型的世界中,有两种以上的模型。其中, 灰度,HSVHLS 是你在计算机视觉中会经常看到的。

灰度很简单。它通过黑白的强度来表示图像和形态,这意味着它只有一个通道。要查看灰度图像,我们需要将彩色模式转换为灰色,就像我们之前对 BGR 图像所做的那样。

*# Convert the image into gray scale
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.imshow(img_gray, cmap = 'gray')*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

实际上,RGB 图像是由三个通道堆叠而成的:R、G 和 b。因此,如果我们选取每个通道并逐一描绘它们,我们就可以理解颜色通道是如何构成的。

*# Plot the three channels of the image
fig, axs = plt.subplots(nrows = 1, ncols = 3, figsize = (20, 20))for i in range(0, 3):
    ax = axs[i]
    ax.imshow(img_rgb[:, :, i], cmap = 'gray')
plt.show()*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

看看上面的图片。这三个图像向您展示了每个通道是如何组成的。在 R 通道图片中,红色饱和度高的部分看起来是白色的。这是为什么呢?这是因为红色部分的值接近 255。在灰度模式下,该值越高,颜色越白。您也可以用 G 或 B 通道来检查这一点,并比较某些部分之间的差异。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

HSV 和 HLS 有一点不同。正如你在上面看到的,它们有一个三维的表示,它更类似于人类的感知方式。 HSV 代表色相、饱和度、明度。 HSL 代表色相、饱和度、明度。HSV 的中心轴是颜色值,而 HSL 的中心轴是光量。沿着中心轴的角度,有色调,实际的颜色。而离中轴线的距离属于饱和。可以按如下方式转换颜色模式。

*# Transform the image into HSV and HLS models
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
img_hls = cv2.cvtColor(img, cv2.COLOR_BGR2HLS)# Plot the converted images
fig, (ax1, ax2) = plt.subplots(nrows = 1, ncols = 2, figsize = (20, 20))
ax1.imshow(img_hsv)
ax2.imshow(img_hls)
plt.show()*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是为什么我们要变换颜色呢?这些是干什么用的?可以给出答案的一个例子是车道检测。请看下图。查看如何在不同的颜色模式下检测车道。在计算机视觉任务中,我们在蒙版的同时进行多种颜色模式的转换。如果你想了解更多关于如何在车道检测任务中应用图像处理的信息,请随时查看由 nachiket tanksale 撰写的 这篇文章

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

RGB vs Grayscale (darkened) vs HSV vs HSL

现在我相信你明白了。图像处理是“数据预处理”它减少噪音,提取有用的模式,使分类和检测任务更容易。因此,所有这些技术,包括我们将在后面讨论的技术,都是为了帮助模型更容易地检测模式。

在图像上绘图

让我们在图像上添加一些数字。现在,我们要去巴黎。你听说过爱情墙吗?这是一面用各种国际语言写满“我爱你”的墙。我们要做的是找到我们语言中的单词,并用一个矩形标记它们。因为我来自韩国,我会在韩语中查找“我爱你”。首先,我将复制原始图像,然后用cv2.rectangle()画一个矩形,我们需要给出左上角和右下角的坐标值。

*# Copy the image
img_copy = img.copy()# Draw a rectangle 
cv2.rectangle(img_copy, pt1 = (800, 470), pt2 = (980, 530), 
              color = (255, 0, 0), thickness = 5)
plt.imshow(img_copy)*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

太好了!我觉得我抓对位置了。让我们再试一次。我可以从图像中看到一个韩文单词,所以这次我会画一个圆圈。用cv2.circle(),我们需要指定它的圆心的点和它的半径的长度。

*# Draw a circle 
cv2.circle(img_copy, center = (950, 50), radius = 50, 
           color = (0, 0, 255), thickness = 5)
plt.imshow(img_copy)*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们也可以在图像上放置文本数据。这次我们为什么不写这面墙的名字呢?使用cv2.putText(),我们可以指定文本的位置、字体和大小。

*# Add text 
cv2.putText(img_copy, text = "the Wall of Love", 
            org = (250, 250),
            fontFace = cv2.FONT_HERSHEY_DUPLEX, 
            fontScale = 2, 
            color = (0, 255, 0), 
            thickness = 2, 
            lineType = cv2.LINE_AA)
plt.imshow(img_copy)*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这真是一面“可爱”的墙,不是吗?自己试试,用你的语言找到“我爱你”!😍

不仅仅是图像

现在我们去了意大利和法国。接下来你想去哪里?我们为什么不放一张地图并标出这些地方呢?我们将创建一个窗口并绘制图形,不是通过指定点,而是通过直接点击窗口。我们先试一圈。我们首先创建一个函数,用鼠标位置和点击的数据画一个圆。

*# Step 1\. Define callback function
**def** draw_circle(event, x, y, flags, param): **if** event == cv2.EVENT_LBUTTONDOWN:
            cv2.circle(img, center = (x, y), radius = 5, 
                       color = (87, 184, 237), thickness = -1) **elif** event == cv2.EVENT_RBUTTONDOWN:        
            cv2.circle(img, center = (x, y), radius = 10,  
                       color = (87, 184, 237), thickness = 1)*

使用cv2.EVENT_LBUTTONDOWNcv2.EVENT_RBUTTONDOWN,当我们按下鼠标按钮时,我们可以带来该位置的数据。鼠标的位置将是(x, y),我们将画一个圆心在该点的圆。

*# Step 2\. Call the window
img = cv2.imread('map.png')cv2.namedWindow(winname = 'my_drawing')
cv2.setMouseCallback('my_drawing', draw_circle)*

我们将设置一张地图作为窗口的背景,并将窗口命名为 my_drawing 。窗口的名称可以是任何东西,但是它应该是相同的,因为它的作用就像窗口的 id。使用cv2.setMouseCallback(),我们在窗口和我们在步骤 1 中创建的函数draw_circle之间建立一个连接。

*# Step 3\. Execution
**while** True:
    cv2.imshow('my_drawing',img)
    **if** cv2.waitKey(10) & 0xFF == 27:
       ** break**cv2.destroyAllWindows()*

现在我们使用 while 循环执行窗口。不要忘记设置断点,除非你正在进行无限循环。if 子句的条件是当我们按键盘上的 ESC 键时关闭窗口。将此保存为文件,并将其导入您的终端。如果你要使用 jupyter 实验室,把代码放在一个单元格中并执行。现在,告诉我!你想去哪?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们试试长方形。由于矩形需要两个点用于cv2.rectangle()中的 pt1pt2 ,我们需要一个额外的步骤来设置第一个点击点为 pt1 和最后一个点为 pt2 。我们将使用cv2.EVENT_MOUSEMOVEcv2.EVENT_LBUTTONUP来检测鼠标的移动。

我们首先将drawing = False定义为默认值。当按下左键时,drawing变为真,我们将第一个位置指定为 pt1 。如果绘图打开,它会将当前点作为 pt2 并在我们移动鼠标时继续绘制矩形。这就像重叠的数字。当左键向上时,drawing变为假,以鼠标的最后位置作为其 pt2 的终点。

*# Initialization
drawing = False
ix = -1
iy = -1# create a drawing function
**def** draw_rectangle(event, x, y, flags, params):

    **global** ix, iy, drawing **if** event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        ix, iy = x, y

    **elif** event == cv2.EVENT_MOUSEMOVE:
        if drawing == True:
            cv2.rectangle(img, pt1=(ix, iy), pt2=(x, y), 
                          color = (87, 184, 237), thickness = -1)

    **elif** event == cv2.EVENT_LBUTTONUP:
        drawing = False
        cv2.rectangle(img, pt1=(ix, iy), pt2=(x, y), 
                     color = (87, 184, 237), thickness = -1)*

将步骤 1 中的draw_circle功能替换为draw_rectangle。请不要忘记在回调函数中做一个改变,cv2.setMouseCallback()也一样。所以整个代码脚本如下。保存这个脚本文件,并在终端或 jupyter 笔记本上运行它。

下一步是什么?

你喜欢第一次使用 OpenCV 吗?您还可以尝试其他功能,如绘制直线或多边形。可以随意查看它的文档,可以在这里 找到 。下一次,我们将讨论更高级的技术,如附加两个不同的图像,图像轮廓和对象检测。

⭐️,你可能也会觉得这些系列很有趣,⭐️

  • 卷积神经网络的基本概念:

*** [## CNN 最直观、最简单的指南

揭开卷积神经网络的神秘面纱

towardsdatascience.com](/the-most-intuitive-and-easiest-guide-for-convolutional-neural-network-3607be47480)

  • 卷积神经网络的高级网络:

[## 深入了解计算机视觉世界:第 1 部分

从 VGG 开始,ResNet 和盗梦空间网络

towardsdatascience.com](/deep-dive-into-the-computer-vision-world-f35cd7349e16)

有你想改正的错误吗?请与我们分享您的见解。我总是乐于交谈,所以请在下面留下评论,分享你的想法。我还在 LinkedIn上分享有趣和有用的资源,所以请随时关注或联系我。下次我会带着另一个有趣的故事回来的!***

初学者的计算机视觉:第 2 部分

原文:https://towardsdatascience.com/computer-vision-for-beginners-part-2-29b3f9151874?source=collection_archive---------3-----------------------

Python 中带滤波的图像处理基础

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

准备是指在实际开始一项任务之前为它做好准备的过程。这可能是写故事、工作面试或数据建模的准备步骤。做好充分的准备,其重要性怎么强调都不为过。如果我们没有进行足够的预处理,那么无论我们有多好的数据,都很难期望得到一个令人满意的结果。

这是 OpenCV 初学者教程的第二部分,完整系列如下:

  1. 理解颜色模型并在图像上绘制图形
  2. 带滤波的图像处理基础
  3. 从特征检测到人脸检测
  4. 轮廓检测和享受一点乐趣

今天我们将讨论如何处理图像。这将是一个预处理阶段。在检测边缘和轮廓时,噪声对检测的准确性有很大影响。因此,去除噪声和控制像素值的强度可以帮助模型专注于一般细节并获得更高的精度。模糊、阈值处理和形态变换是我们用于此目的的技术。

这篇文章假设你已经熟悉卷积的概念。但如果不是这样,我想推荐你先查一下 这个帖子 。本教程的完整代码也可以在 Github 上找到。现在让我们一个一个的来看看如何用 OpenCV 应用图像过滤。

模糊

模糊的目标是执行降噪。但是我们在这里要格外小心。如果我们对高分辨率的图像应用边缘检测算法,我们会得到太多我们不感兴趣的检测结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

相反,如果我们过度模糊图像,我们会丢失数据。因此,我们需要找到一个足够的模糊量,我们将申请没有失去理想的边缘。

有几种技术用于实现模糊效果,但我们将讨论 OpenCV 中使用的四种主要技术: 平均模糊、高斯模糊、中值模糊 双边滤波 。所有这四种技术都有一个共同的基本原理,即使用滤波器(内核)对图像应用卷积运算。在四种模糊方法之间,应用过滤器的值是不同的。

平均模糊取给定内核区域下所有像素值的平均值,替换中心值。例如,假设我们有一个大小为 5X5 的内核。我们计算卷积结果的平均值,并将结果放在给定区域的中心。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

那么如果我们增加内核的大小会是什么样的呢?随着过滤器的尺寸变大,像素值将更加规范化。因此,我们可以预期图像会变得更加模糊。让我们用如下代码检查一下结果。(为了比较,我将继续将原始图像附加到结果中)

# Import the image and convert to RGB 
img = cv2.imread('text.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# Plot the image with different kernel sizes
kernels = [5, 11, 17]fig, axs = plt.subplots(nrows = 1, ncols = 3, figsize = (20, 20)) **for** ind, s **in** enumerate(kernels):
    img_blurred = **cv2.blur(img, ksize = (s, s))**
    ax = axs[ind]
    ax.imshow(img_blurred)
    ax.axis('off')
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

中等模糊与平均模糊相同,只是它使用中值而不是平均值。因此,当我们必须处理图像中的突发噪声时,如“椒盐噪声”,使用中等模糊比平均模糊更好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The shape of a Gaussian filter (on the left) and a Bilateral filter (on the right)

高斯模糊无非是使用其值具有高斯分布的内核。这些值是由高斯函数生成的,因此它需要一个 sigma 值作为其参数。正如你在上面的图像中看到的,内核的值在中心附近变高,在角落附近变小。最好将这种方法应用于具有正态分布的噪声,例如白噪声

双边滤波是高斯模糊的高级版本。模糊不仅会产生溶解噪声,还会平滑边缘。双边滤波可以在去除噪声的同时保持边缘清晰。它使用高斯分布值,但同时考虑了距离和像素值的差异。因此需要sigmaSpacesigmaColor作为参数。

# Blur the image 
img_0 = **cv2.blur**(img, ksize = (7, 7))
img_1 = **cv2.GaussianBlur**(img, ksize = (7, 7), sigmaX = 0)   
img_2 = **cv2.medianBlur**(img, 7)
img_3 = **cv2.bilateralFilter**(img, 7, sigmaSpace = 75, sigmaColor =75)# Plot the images
images = [img_0, img_1, img_2, img_3]
fig, axs = plt.subplots(nrows = 1, ncols = 4, figsize = (20, 20))**for** ind, p **in** enumerate(images):
    ax = axs[ind]
    ax.imshow(p)
    ax.axis('off')
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

阈值处理

阈值处理将图像转换成二值图像。我们需要设置阈值和最大值,然后我们相应地转换像素值。有五种不同类型的阈值处理: 二值化、二值化的逆、阈值为零、 阈值截断

img = cv2.imread('gradation.png')# Thresholding 
_, thresh_0 = cv2.threshold(img, 127, 255, **cv2.THRESH_BINARY**)
_, thresh_1 = cv2.threshold(img, 127, 255, **cv2.THRESH_BINARY_INV**)
_, thresh_2 = cv2.threshold(img, 127, 255, **cv2.THRESH_TOZERO**)
_, thresh_3 = cv2.threshold(img, 127, 255, **cv2.THRESH_TOZERO_INV**)
_, thresh_4 = cv2.threshold(img, 127, 255, **cv2.THRESH_TRUNC**)# Plot the images
images = [img, thresh_0, thresh_1, thresh_2, thresh_3, thresh_4]fig, axs = plt.subplots(nrows = 2, ncols = 3, figsize = (13, 13))
**for** ind, p **in** enumerate(images):
    ax = axs[ind//3, ind%3]
    ax.imshow(p)
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你可以看到每种类型的阈值是如何用数学方法表示的,并且 I(x,y) 是该点的强度,或者(x,y)处的像素值。但是我更喜欢直观的理解概念。看一下右边的图片。这些图片有助于你理解不同类型之间的区别。

但是你不认为只取一个阈值并将其应用于图像的所有部分太苛刻了吗?如果我们有一张在不同区域有不同亮度的照片会怎么样?在这种情况下,将一个值应用于整个图像将是一个糟糕的选择。更好的方法是对图像的每个部分使用不同的阈值。还有一种叫做 自适应阈值 的技术,就是为这个问题服务的。通过计算图像邻域内的阈值,我们可以从光照变化的图像中获得更好的结果。

# Convert the image to grayscale
img = cv2.imread('text.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# Adaptive Thresholding
_, thresh_binary = cv2.threshold(img, thresh = 127, maxval = 255, type = cv2.THRESH_BINARY)
adap_mean_2 = cv2.adaptiveThreshold(img, 255, 
                                    **cv2.ADAPTIVE_THRESH_MEAN_C**, 
                                    **cv2.THRESH_BINARY**, 7, 2)
adap_mean_2_inv = cv2.adaptiveThreshold(img, 255, 
                                        **cv2.ADAPTIVE_THRESH_MEAN_C**, 
                                        **cv2.THRESH_BINARY_INV**, 7, 2)
adap_mean_8 = cv2.adaptiveThreshold(img, 255, 
                                    **cv2.ADAPTIVE_THRESH_MEAN_C**, 
                                    cv2.THRESH_BINARY, 7, **8**)
adap_gaussian_8 = cv2.adaptiveThreshold(img, 255, 
                                    **cv2.ADAPTIVE_THRESH_GAUSSIAN_C**, 
                                    cv2.THRESH_BINARY, 7, **8**)

我们需要将彩色模式转换为灰度模式,以应用自适应阈值处理。自适应阈值的参数有maxValue(上面我设置了 255)、adaptiveMethodthresholdTypeblockSizeC。而这里的自适应方法有两种:ADAPTIVE_THRESH_MEAN_CADAPTIVE_THRESH_GAUSSIAN_C。让我们看看图像是如何不同地产生的。

# Plot the images
images = [img, thresh_binary, adap_mean_2, adap_mean_2_inv, 
          adap_mean_8, adap_gaussian_8]
fig, axs = plt.subplots(nrows = 2, ncols = 3, figsize = (15, 15))**for** ind, p **in** enumerate(images):
    ax = axs[ind%2, ind//2]
    ax.imshow(p, cmap = 'gray')
    ax.axis('off')
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们有原始图像,左边一行是二值化的图像。将此与上面一行的第二个和第三个图像进行比较,这是由ADAPTIVE_THRESH_MEAN_C生成的。它显示了比二进制阈值更详细的结果。我们还可以看到,当 C 值较大时,它变得更加明显。C表示我们将从平均值或加权平均值中减去多少。有了右边这两幅图,我们还可以比较 C 值相同的ADAPTIVE_THRESH_MEAN_CADAPTIVE_THRESH_GAUSSIAN_C的效果。

梯度

我相信我们已经熟悉了梯度的概念。在数学中,梯度在几何上表示一个多变量函数的图形的斜率。因为它是一个向量值函数,所以它以方向和幅度作为其分量。这里我们也可以把同样的概念应用到图像的像素值上。图像梯度表示强度或颜色模式的方向变化,我们可以使用这个概念来定位边缘。

# Apply gradient filtering
sobel_x = **cv2.Sobel**(img, cv2.CV_64F, **dx = 1, dy = 0**, ksize = 5)
sobel_y = **cv2.Sobel**(img, cv2.CV_64F, **dx = 0, dy = 1**, ksize = 5)
blended = **cv2.addWeighted**(src1=sobel_x, alpha=0.5, src2=sobel_y,
                          beta=0.5, gamma=0)
laplacian = **cv2.Laplacian**(img, cv2.CV_64F)

索贝尔运算 同时使用高斯平滑和微分。我们通过cv2.Sobel()应用它,有两个不同的方向可用:垂直(sobel_x)和水平(sobel_y)。dxdy表示衍生产品。当dx = 1时,操作者计算像素值沿水平方向的导数以进行过滤。

通过对sobel_xsobel_y两个滤波器求和,我们也可以在两个方向上应用。使用函数cv2.addWeighted(),我们可以计算滤波器的加权和。正如你在上面的代码单元中看到的,我给了两个过滤器相同的权重。

拉普拉斯运算使用 x 和 y 的二阶导数,数学表达式如下所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一张图胜过千言万语。让我们看看图像是什么样的。

# Plot the images
images = [sobel_x, sobel_y, blended, laplacian]
plt.figure(figsize = (20, 20))
for i in range(4):
    plt.subplot(1, 4, i+1)
    plt.imshow(images[i], cmap = 'gray')
    plt.axis('off')
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

很明显,第一和第二图像具有方向性图案。通过第一张图片,我们可以清楚地看到垂直方向的边缘。在第二张图中,我们可以看到水平边缘。和第四图像,示出了两个方向上的边缘。

形态转换

也可以通过过滤来操纵图像的形状,这被称为*。先说侵蚀和膨胀。*

腐蚀是缩小图形的技术,通常以灰度处理。过滤器的形状可以是矩形、椭圆形和十字形。通过应用过滤器,我们移除给定区域下的任何 0 值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们看看这些如何在代码中实现。

*img = cv2.imread('simpson.jpg')# Create erosion kernels 
kernel_0 = np.ones((9, 9), np.uint8)
kernel_1 = cv2.getStructuringElement(**cv2.MORPH_ELLIPSE**, (9, 9))
kernel_2 = cv2.getStructuringElement(**cv2.MORPH_CROSS**, (9, 9))kernels = [kernel_0, kernel_1, kernel_2]# Plot the images
plt.figure(figsize = (20, 20))
for i in range(3):
    img_copy = img.copy()
    img_copy = cv2.erode(img_copy, kernels[i], iterations = 3)
    plt.subplot(1, 3, i+1)
    plt.imshow(img_copy)
    plt.axis('off')
plt.show()*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

看看辛普森一家是如何通过使用不同类型的内核而缩小的。(对辛普森失去双手感到抱歉!)我们可以看到,具有椭圆过滤器的图像以“圆形”方式被侵蚀,而具有方形形状的基本过滤器的图像以“线性”方式被侵蚀。最后一个十字滤镜显示它以“对角线”方式收缩。

膨胀与侵蚀相反。它使物体膨胀,其操作也将与侵蚀相反。让我们用如下代码检查一下结果。

*# Apply dilation
kernel = np.ones((9, 9), np.uint8)
img_dilate = cv2.dilate(img, kernel, iterations = 3)plt.figure(figsize = (20, 10))
plt.subplot(1, 2, 1); plt.imshow(img, cmap="gray")
plt.subplot(1, 2, 2); plt.imshow(img_dilate, cmap="gray")
plt.show()*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

开启关闭*操作是腐蚀和膨胀的混合版本。打开先进行腐蚀,然后对腐蚀的结果进行膨胀,而关闭先进行膨胀,然后进行腐蚀。*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如上图所示,闭合有助于检测图形的整体轮廓,而打开则适合检测子模式。我们可以用下面显示的函数cv2.morphologyEx()来实现这些操作符。参数op表示我们将使用哪种类型的操作符。

*# Apply the operations
kernel = np.ones((9, 9), np.uint8)img_open = cv2.morphologyEx(img, op= **cv2.MORPH_OPEN**, kernel)
img_close = cv2.morphologyEx(img, op= **cv2.MORPH_CLOSE**, kernel)
img_grad = cv2.morphologyEx(img, op= **cv2.MORPH_GRADIENT**, kernel)
img_tophat = cv2.morphologyEx(img, op= **cv2.MORPH_TOPHAT**, kernel)
img_blackhat = cv2.morphologyEx(img, op= **cv2.MORPH_BLACKHAT**, kernel)# Plot the images
images = [img, img_open, img_close, img_grad, 
          img_tophat, img_blackhat]fig, axs = plt.subplots(nrows = 2, ncols = 3, figsize = (15, 15))
**for** ind, p **in** enumerate(images):
    ax = axs[ind//3, ind%3]
    ax.imshow(p, cmap = 'gray')
    ax.axis('off')
plt.show()*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

请注意,在打开滤镜和关闭滤镜的图像中,Simpson 的手被描绘得不同。梯度过滤器(MORPH_CGRADIENT)是从膨胀到侵蚀减去的区域。礼帽滤镜(MORPH_TOPHAT)是从打开到原始图像减去的区域,而黑色热滤镜(MORPH_BLACKHAT)是从关闭减去的区域。我推荐你访问这里的以获得关于形态运算符的进一步解释。

下一步是什么?

你喜欢各种各样的图像处理技术吗?除了我们已经讨论过的东西,OpenCV 中还有其他可用的东西。因此,请不要犹豫,赶快访问并查看 OpenCV 文档 。下一次将是关于检测技术,如轮廓检测和面部检测。

有你想改正的错误吗?请与我们分享您的见解。我总是乐于交谈,所以请在下面留下评论,分享你的想法。我还在 LinkedIn 上分享有趣和有用的资源,欢迎随时关注或联系我。我将带着故事的下一个系列回来。敬请期待!

初学者的计算机视觉:第 3 部分

原文:https://towardsdatascience.com/computer-vision-for-beginners-part-3-79de62dbeef7?source=collection_archive---------8-----------------------

从特征检测到人脸检测

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

检测任务是计算机视觉的主要任务之一,我们有许多方法可以利用这项技术。识别出现时可能是关键的错误,但人眼无法识别。探测不安全和危险的动作或时刻以拯救生命。为自动驾驶汽车感知空间信息。使用物体检测的例子数不胜数,让这些任务自动化将给我们带来安全和效率。

这是 OpenCV 初学者教程的第三部分,完整系列如下:

  1. 理解颜色模型并在图像上绘制图形
  2. 带滤波的图像处理基础知识
  3. 从特征检测到人脸检测
  4. 轮廓检测和享受一点乐趣

我们已经讨论了几种颜色模式以及如何在图像上绘制图形,例如矩形和圆形。然后在第 2 部分,我们谈到了图像处理的概念,如模糊,梯度,腐蚀,膨胀等。今天,我们将应用这些概念来检测图像的特征,并在最后进行人脸检测。

本文假设您已经遵循了前面的步骤,或者您已经知道这些概念。但如果不是这样,请查看本系列前面的部分。本教程的完整代码可在 Github 上获得。现在让我们开始吧!

边缘检测

边缘检测 是指识别图像中亮度变化剧烈或不连续的点。我们可以用那些点画线段,这些线段叫做 。实际上,我们上次已经学习了一种边缘检测技术。你还记得吗?用索贝尔和拉普拉斯运算进行梯度滤波。通过计算给定方向上像素值的导数,梯度滤波可以描绘图像的边缘。

Canny 检测 是另一种边缘检测技术。这是最流行的边缘检测算法之一,分四步进行: 降噪,寻找梯度及其方向,非最大抑制滞后阈值

该算法从高斯模糊开始,我想我们已经知道去除图像中噪声的原因。然后用 Sobel 核寻找图像的亮度梯度。利用导出的梯度和方向,检查每个像素的某个点是否是其周围点的局部最大值。如果不是,这一点被抑制为零(完全不存在,黑色)。这叫做 非最大抑制

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果该点被认为是局部最大值,则进入下一阶段。最后一个阶段是最后一个决定阶段,决定前面步骤中的边是否真的是边。这被称为 滞后阈值 ,这里我们需要两个阈值。

给定两个不同的阈值,我们得到三个范围的值。因此,如果一个点的强度梯度高于上限阈值,它将被认为是“确定边缘”如果一个点的梯度低于下限阈值,该点将被丢弃。在梯度处于两个阈值中间的情况下,我们看到它与其他“确定边缘”点的连通性。如果没有联系,它也会被丢弃。

img = cv2.imread('images/giraffe.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# Canny detection without blurring
edges = **cv2.Canny(**image=img, threshold1=127, threshold2=127**)**plt.figure(figsize = (20, 20))
plt.subplot(1, 2, 1); plt.imshow(img)
plt.axis('off')
plt.subplot(1, 2, 2); plt.imshow(edges)
plt.axis('off')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我只是在没有模糊的情况下使用了两个阈值的中间值,结果并不理想。现在让我们这次尝试不同的阈值。

# Set the lower and upper threshold
med_val = np.median(img)lower = int(max(0, .7*med_val))
upper = int(min(255, 1.3*med_val))

为了了解模糊如何改变结果,我将应用两种不同大小的内核,(5x5)和(9x9)。我将尝试通过增加 100 来更改上限阈值。因此,我们有 4 种类型的处理图像,如下所示:

# Blurring with ksize = 5 
img_k5 = cv2.blur(img, ksize = (5, 5))# Canny detection with different thresholds
edges_k5 = cv2.Canny(img_k5, threshold1 = lower, threshold2 = upper)
edges_k5_2 = cv2.Canny(img_k5, lower, upper+100)# Blurring with ksize = 9 
img_k9 = cv2.blur(img, ksize = (9, 9))# Canny detection with different thresholds
edges_k9 = cv2.Canny(img_k9, lower, upper)
edges_k9_2 = cv2.Canny(img_k9, lower, upper+100)# Plot the images
images = [edges_k5, edges_k5_2, edges_k9, edges_k9_2]
plt.figure(figsize = (20, 15))
for i in range(4):
    plt.subplot(2, 2, i+1)
    plt.imshow(images[i])
    plt.axis('off')
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

正如你在上面看到的,模糊有助于去除噪声,我们用(9x9)大小的内核得到了更好的结果。此外,阈值上限越高,我们得到的结果越好。

角点检测

角点检测是另一种广泛应用于目标检测、运动检测、视频跟踪等领域的检测算法。什么是图像处理中的角点?怎样才能用像素定义一个角呢?我们把角看作是边相交的地方。那我们怎么找到他们?首先找到所有的边,然后定位它们相互交叉的点?其实我们还有另外一种让事情更有效率的方法,那就是 哈里斯石&托马西

这些算法工作如下。我们检测各个方向上强度值有相当大变化的点。然后我们构造一个矩阵从中提取特征值。这些特征值是为了得分来决定它是否是一个角。数学表达式如下所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在让我们看看如何用代码实现这些。我们首先需要将图像转换成灰度。 哈里斯角点检测 可以用 OpenCV 中的函数cv2.cornerHarris()进行。

img = cv2.imread('images/desk.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)# Apply Harris corner detection
dst = **cv2.cornerHarris(**img_gray, blockSize = 2, ksize = 3, k = .04**)**

参数blockSize是被认为是邻域的窗口的大小,而k是哈里斯检测器自由参数,如上面的等式所示。结果是分数 R,我们将使用它来检测角点。

# Spot the detected corners
img_2 = img.copy()
img_2[dst>0.01*dst.max()]=[255,0,0]# Plot the image
plt.figure(figsize = (20, 20))
plt.subplot(1, 2, 1); plt.imshow(img)
plt.axis('off')
plt.subplot(1, 2, 2); plt.imshow(img_2)
plt.axis('off')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这次我们试试 Shi-Tomasi 角点检测。我们可以用函数cv2.goodFeaturesToTrack()来使用它。我们按照最大可能性(maxCorners)设置最大数量的角点。我们还指定了最小距离(minDistance)和最小质量等级(qualityLevel),它们被认为是角点。在我们得到检测到的角点后,我们将用圆圈标记这些点,如下所示。

# Apply Shi-Tomasi corner detection
corners = **cv2.goodFeaturesToTrack(**img_gray, maxCorners = 50, 
                                  qualityLevel = 0.01, 
                                  minDistance = 10**)**
corners = np.int0(corners)# Spot the detected corners
img_2 = img.copy()
for i in corners:
    x,y = i.ravel()
    cv2.circle(img_2, center = (x, y), 
               radius = 5, color = 255, thickness = -1)# Plot the image
plt.figure(figsize = (20, 20))
plt.subplot(1, 2, 1); plt.imshow(img)
plt.axis('off')
plt.subplot(1, 2, 2); plt.imshow(img_2)
plt.axis('off')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

人脸检测

我们要看的最后一个特征是一张脸。 人脸检测 是一种识别数字图像中人脸的存在和位置的技术。我要你把人脸检测和人脸识别 区分开来,人脸识别是指通过人脸来检测一个人的身份。所以人脸检测并不能告诉我们检测到的人脸属于谁。

人脸检测基本上是一个分类任务,因此它被训练来分类是否有目标对象。而 基于 Haar 特征的级联分类器 是 OpenCV 中可用的人脸检测模型之一。这是一个预训练模型,这意味着它已经完成了数千张图像的训练。理解该算法的 4 个要点是 哈尔特征提取、积分图像、Adaboost级联分类器

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

类哈尔特征 是用于物体检测的图像滤波器或图像核,示例如上。它们的名字源于它们与最初由 Alfréd Haar 提出的 Haar 小波的直觉相似性。在检测过程中,我们通过图像上的窗口,用过滤器进行卷积运算,以查看图像中是否有我们要寻找的特征。这里是 视频 ,它可视化了检测是如何工作的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

那么我们如何决定在一个给定的区域中是否有一个想要的特性呢?我们来看看上图。我们有一个内核,它的上半部分是深色的,下半部分是浅色的。然后,我们得到每个区域的像素值的平均值,并减去两者之间的差距。如果结果高于一个阈值,比如说 0.5,那么我们得出结论,这就是我们正在检测的特征。我们对每个内核重复这个过程,同时在图像上滑动窗口。

虽然这不是一个复杂的计算,但当我们在整个图像中考虑它时,总计算量变得巨大。如果你看过上面提到的视频,你会对所涉及的计算量有直觉。而这正是一个 积分图 发挥作用的地方。积分图像是一种图像表示方式,是为了使特征评价更快、更有效而衍生出来的。

如下图所示,左边是一幅图像的像素,右边是一幅完整的图像。从左上角开始,它计算给定矩形区域下像素的累积和。在积分图像上,虚线框内的像素之和写在右边框的右下点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有了这个预先计算的表,我们可以通过子矩形(红色、橙色、蓝色和紫色的方框)的值简单地得到某个区域的总和值。

所以我们用积分图像解决了计算量。但是我们还没完。想象一下,当检测窗口处于没有物体或人脸的空白背景时。如果在这样的部分执行相同的过程,仍然是浪费时间。还有一个让这个探测器更快的因素。实现 一个 级联分类器与 Adaboost!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

级联分类器构建逐步的阶段,并给出类哈尔特征之间的顺序。功能的基本形式在早期阶段实现,而更复杂的功能仅适用于那些有希望的区域。并且在每个阶段,Adaboost 模型将通过集合弱学习者来训练。如果一个子部分或子窗口在前一阶段被归类为“非人脸区域”,它将被拒绝进入下一步。这样做,我们只能考虑幸存的,并实现更高的速度。

我们的英雄在哪里?

为了让这个教程更有趣,我想实现这个级联分类器来检测我们的漫威英雄的脸。(机器学习应该很好玩,你说呢?😃😃)让我们有请漫威上尉作为我们的第一位客人。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们将只使用这张图片的一部分。所以让我们先得到她脸部周围的感兴趣区域,然后将图像转换成灰度。只使用一个通道的原因是因为我们只对特征的光强度变化感兴趣。

*cap_mavl = cv2.imread('images/captin_marvel.jpg')# Find the region of interest
roi = cap_mavl[50:350, 200:550]
roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
plt.imshow(roi, cmap = 'gray')*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Haar 级联分类器文件基本上是 OpenCV 附带的。你可以在你电脑上的 OpenCV 文件夹中找到它们。或者你可以简单的在这里 下载文件

*# Load Cascade filter 
face_cascade = cv2.CascadeClassifier('haarcascades/**haarcascade_frontalface_default.xml**')*

接下来,我们将创建一个函数来检测一张脸,并在其周围绘制一个矩形。为了检测面部,我们可以使用上面加载的分类器face_cascade的方法.detectMulitiScale()。它返回识别区域的四个点,所以我们将在那个位置画一个矩形。scaleFactor是每个图像尺度下图像尺寸减小多少的参数,而minNeighbors是每个候选矩形应该训练多少个邻居的参数。现在让我们把这个函数应用到图像上,看看结果。

*# Create the face detecting function 
**def** detect_face(img)**:**

    img_2 = img.copy()
    face_rects = **face_cascade.detectMultiScale(**img_copy, 
                                               scaleFactor = 1.1,
                                               minNeighbors = 3**)

    for** (x, y, w, h) **in** face_rects:
        cv2.rectangle(img_2, (x, y), (x+w, y+h), (255, 255, 255), 3)

    **return** img_2# Detect the face
roi_detected = detect_face(roi)
plt.imshow(roi_detected, cmap = 'gray')
plt.axis('off')*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

太好了!我觉得这个还是比较满意的。这次为什么不干脆叫其他英雄?我们也可以对有多张脸的图像实现这个分类器。

*# Load the image file and convert the color mode
avengers = cv2.imread('images/avengers.jpg')
avengers = cv2.cvtColor(avengers, cv2.COLOR_BGR2GRAY)# Detect the face and plot the result
detected_avengers = detect_face(avengers)
display(detected_avengers, cmap = 'gray')*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

是的,有时捕捉“非人脸”对象或错过“真实人脸”会导致失败。有趣的是,它成功地发现了蜘蛛侠,却把美国队长和黑寡妇的手误认为眼睛。我们通常会得到更好的结果,一张脸看着前方,清楚地显示出额头和眼睛。

想试试你的吗?

你想试试你的网络摄像头吗?我们可以应用同样的过程。将下面的代码脚本保存为一个文件,并将其导入到您的终端上。如果你要使用 Jupyter 笔记本,把代码放在一个单元格中并执行。你可以按 ESC 键关闭窗口。

它成功检测到你的脸了吗?希望它不会选择你的鼻孔做眼睛。😅

下一步是什么?

你喜欢这个故事吗?除了正面人脸分类器,还有眼睛、上半身、下半身等各种模型。你也可以试试检测俄罗斯车牌的模型。所以我建议你也玩玩它。你想测试你对图像处理的理解吗?试试这个 25 题图像处理 。这里有一些很棒的文章,为你应该检查的问题提供了详细的解释。

* [## 我用 25 个问题来测试一个数据科学家关于交互式代码的图像处理-第 1 部分

所以我找到了这个神奇的博客作者 Faizan Shaikh,他的博客上有一些神奇的东西!所以请检查他…

towardsdatascience.com](/my-take-on-25-questions-to-test-a-data-scientist-on-image-processing-with-interactive-code-part-1-a6196f535008) [## 我用 25 个问题来测试一个数据科学家对交互式代码的图像处理-第 2 部分

所以我找到了这个神奇的博客作者 Faizan Shaikh,他的博客上有一些神奇的东西!所以请检查他…

towardsdatascience.com](/my-take-on-25-questions-to-test-a-data-scientist-on-image-processing-with-interactive-code-part-2-77eacfd96cf9)

有你想改正的错误吗?请与我们分享您的见解。我总是乐于交谈,所以请在下面留下评论,分享你的想法。我还在 LinkedIn 上分享有趣且有用的资源,欢迎随时关注并联系我。我将带来另一个有趣的计算机视觉故事。敬请关注!*

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值