[科研图像处理]用matlab平替image-j,有点麻烦,但很灵活!

news2024/11/26 20:18:31

做材料与生物相关方向的同学应该对image-j并不陌生,前几天有个师兄拜托我用image-j分析一些图片,但使用过后发现我由于不了解image-j的工作流程而对结果并不确信,而且image-j的功能无法拓展,对有些图片的处理效果并不好,因此我想到自己用matlab实现类似的功能,虽然没有友好的互动界面,但好在大家可以以此为基础,自己设计功能,更好得适配自己的研究方向。
测试文件与源程序下载地址,提取码: tcxa
视频教程(B站)

⏰:V1.0目前支持的功能:
😀:图像的开闭运算,分别对应分离细小连接填充细小空洞
😀:二值化:支持单个自动阈值、单个手动阈值、手动区间阈值
😀:筛选颗粒:支持基于圆度筛选、基于面积大小筛选
😀:图像统计:支持颗粒占全图比例、图像真实面积、颗粒真实面积、颗粒数量统计

下载后设置好matlab的工作目录,
在这里插入图片描述

打开main.m文件开始使用,我把所有需要修改的地方都放在最前面:
在这里插入图片描述
建议一开始使用测试图片的时候,对这两项做如下设置:

auto_segmentation = true;          %是否使用自动阈值分割
Interval_segmentation = false;      %是否使用区间阈值分割

完整代码

clear
clc
close all;%关闭图片
%% 这里是需要修改的
image_dir = 'test.png';             %读取文件,修改为你图片的名字
fill_image = false;                 %是否要填充图像,true会开启膨胀加腐蚀
separate_image = false;             %是否要分离图像,true会开启腐蚀加膨胀
SE1 = strel('square',8);            %得到边长为13的方形结构元,腐蚀和膨胀的结构元大小,可以调整的大小看看效果,点密集时候需要调整,dense_image为false时无效
colors = [0,255,0];                 %调颜色,默认红色

auto_segmentation = false;          %是否使用自动阈值分割
level = 200;                         %二值化阈值,auto_segmentation为true时该值无效

Interval_segmentation = false;      %是否使用区间阈值分割
lowerThreshold = 25;                %区间阈值分割下限Interval_segmentation为false时该值无效
upperThreshold = 61;                %区间阈值分割上限Interval_segmentation为false时该值无效

desiredCircularity_bottom = 0.0;    %设置所需的圆度阈值下限,越大越圆,范围0-1
modify_threshold_top = false;       %是否需要修改圆度阈值上限
desiredCircularity_top = 0.6;       %圆度阈值上限值,threshold_top_modify为false时该值无效

ruler_val = 50;                     %比例尺标量值
unit = 'um^2';                      %比例尺单位
ruler_l = 557;                      %比例尺左端像素位置(x)
ruler_r = 744;                      %比例尺右端像素位置(x)

particle_area_thres = 0;         %颗粒大小阈值下限,单位为unit
%% 预处理
imagetest1 = imread(image_dir);
imagetest_copy = imagetest1;
mysize=size(imagetest1);

if numel(mysize) == 2
  imagetest1 = cat(3,imagetest1,imagetest1,imagetest1); %将灰度图像转换为彩色图像
  imagetest_copy = cat(3,imagetest_copy,imagetest_copy,imagetest_copy);
end
imagetest1 = rgb2gray(imagetest1);
imagetest1_copy = imagetest1;

imshow(imagetest_copy)
impixelinfo%通过左下角的提示看比例尺坐标

%Filter = fspecial('average',[3,3]);

% gausFilter1 = fspecial('gaussian',[7,7],0.6);
% imagetest1 = imfilter(imagetest1,gausFilter1);
% imagetest_copy_Gau = imagetest1;

%imagetest_copy = rgb2gray(imagetest_copy);
%I2 = im2bw(imagetest1, 0.25);

if auto_segmentation
    fprintf(2,'注意你使用了自动阈值\n');
    level = graythresh(imagetest1); 
    imagetest1 = imbinarize(imagetest1, level);
elseif (~auto_segmentation&&~Interval_segmentation)
    fprintf(2,'注意你使用了手动阈值\n');
    imagetest1 = imbinarize(imagetest1, level/255);
end

if Interval_segmentation
    fprintf(2,'注意你使用了区间阈值\n');
    imagetest1 = (imagetest1_copy >= lowerThreshold) & (imagetest1_copy <= upperThreshold);%区间二值化
end
%% 腐蚀加膨胀
if fill_image
    fprintf(2,'注意你开启了填充\n')
    imagetest1 = imdilate(imagetest1,SE1);
    imagetest1 = imerode(imagetest1,SE1); 
end
if separate_image
    fprintf(2,'注意你开启了分离\n')
    imagetest1 = imerode(imagetest1,SE1); 
    imagetest1 = imdilate(imagetest1,SE1);
end
%% 圆度筛选封闭区域
labeledImage = bwlabel(imagetest1);%封闭空间标签
props = regionprops(labeledImage, 'Area', 'Perimeter');%实例化
circularity = (4 * pi * [props.Area]) ./ ([props.Perimeter].^2+0.0001);%求圆度

if ~modify_threshold_top
    desiredCircularity_top = max(circularity);% 设置所需的圆度阈值上限,一般不用动
end
selectedLabels = find((desiredCircularity_top > circularity) & (circularity> desiredCircularity_bottom));
selectedImage = ismember(labeledImage, selectedLabels);%根据圆度值做筛选
fprintf(2,['圆度阈值设置为:',num2str(desiredCircularity_bottom),'-',num2str(desiredCircularity_top),'\n']);
fprintf(2,['面积阈值设置为:',num2str(particle_area_thres),unit,'\n'])
%% 展示结果
figure
subplot(2,2,1);
%imshow(imagetest1);
imshow(imagetest_copy);%原图
subplot(2,2,2);
imhist(imagetest_copy)

subplot(2,2,3);
%imshow(imagetest_copy_Gau);
imshow(selectedImage);%展示筛选圆度之后的图像
%% 求解与图像结果美化
sum1 = sum(selectedImage(:));%求像素总数
m = size(imagetest_copy,1);
n = size(imagetest_copy,2);
sum2 = m * n;%原图总像素数
Proportion = sum1/sum2;%求比例
disp(['所选区域占全图的比例:',num2str(Proportion*100),'%'])
real_area = m * n * (ruler_val / (ruler_r - ruler_l))^2;
disp(['全图真实面积:',num2str(real_area),unit])
disp(['选区真实面积:',num2str(real_area*Proportion),unit])

R = imagetest_copy(:,:,1);
G = imagetest_copy(:,:,2);
B = imagetest_copy(:,:,3);

%默认红色
R(selectedImage)=colors(1);
G(selectedImage)=colors(2);      
B(selectedImage)=colors(3);
image_output=cat(3,R,G,B); 

% I = double(selectedImage).*double(I)
% image_output = imfuse(imagetest_copy,I)

subplot(2,2,4);
imshow(image_output)%原图与红色mask的叠加

image_output = uint8(image_output);
imwrite(image_output,'result.png')%保存

selectedImage_copy = selectedImage;%二值化图像
particle_area = regionprops(selectedImage_copy, 'Area');%实例化
disp(['颗粒总数(根据圆度筛选后):',num2str(size(particle_area,1)),'个'])
particle_area_val = [particle_area.Area]*(ruler_val / (ruler_r - ruler_l))^2;%真实世界的面积

vector_particle = [];
for i= 1:size(particle_area_val,2)
    if particle_area_val(i) > particle_area_thres
        vector_particle = [vector_particle, particle_area_val(i)];
    end
end
labeledImage_2 = bwlabel(selectedImage_copy);%封闭空间标签
selectedLabels_2 = find(particle_area_val > particle_area_thres);
selectedImage_copy = ismember(labeledImage_2, selectedLabels_2);%根据面积做筛选

figure
imshow(selectedImage_copy)

mean_particle_real = mean(vector_particle);
disp(['根据面积筛选后颗粒个数:',num2str(size(selectedLabels_2,2))])
disp(['根据面积筛选后平均颗粒真实面积:',num2str(mean_particle_real),unit])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1178930.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【网络协议】聊聊HTTPDNS如何工作的

传统 DNS 存在哪些问题&#xff1f; 域名缓存问题 我们知道CND会进行域名解析&#xff0c;但是由于本地会进行缓存对应的域名-ip地址&#xff0c;所以可能出现过期数据的情况。 域名转发问题 出口 NAT 问题 域名更新问题 解析延迟问题 因为在解析DNS的时候&#xff0c;需要进行…

【C语言】函数的系统化精讲(二)

&#x1f308;write in front :&#x1f50d;个人主页 &#xff1a; 啊森要自信的主页 &#x1f308;作者寄语 &#x1f308;&#xff1a; 小菜鸟的力量不在于它的体型&#xff0c;而在于它内心的勇气和无限的潜能&#xff0c;只要你有决心&#xff0c;就没有什么事情是不可能的…

vue3错误排查-POST请求的body参数 传参方式form-data和json

问题&#xff1a;vue3实现登录功能&#xff0c;登录成功后 跳转到登陆后的界面 一秒后 闪退回登录页 对应的输出结果也一闪而过&#xff0c;反复复查了代码&#xff0c;没问题。 自测&#xff1a;进行断点输出调试。强行跳转到登陆后的界面&#xff0c;查看输出的结果。 没有报…

安全操作(安卓推流)程序

★ 安全操作项目 项目描述&#xff1a;安全操作项目旨在提高医疗设备的安全性&#xff0c;特别是在医生离开操作屏幕时&#xff0c;以减少非授权人员的误操作风险。为实现这一目标&#xff0c;我们采用多层次的保护措施&#xff0c;包括人脸识别、姿势检测以及二维码识别等技术…

Linux 实现原理 — NUMA 多核架构中的多线程调度开销与性能优化

前言 NOTE&#xff1a;本文中所指 “线程” 均为可执行调度单元 Kernel Thread。 NUMA 体系结构 NUMA&#xff08;Non-Uniform Memory Access&#xff0c;非一致性存储器访问&#xff09;的设计理念是将 CPU 和 Main Memory 进行分区自治&#xff08;Local NUMA node&#x…

1070 结绳

一.问题&#xff1a; 给定一段一段的绳子&#xff0c;你需要把它们串成一条绳。每次串连的时候&#xff0c;是把两段绳子对折&#xff0c;再如下图所示套接在一起。这样得到的绳子又被当成是另一段绳子&#xff0c;可以再次对折去跟另一段绳子串连。每次串连后&#xff0c;原来…

【网络安全 --- web服务器解析漏洞】IIS,Apache,Nginx中间件常见解析漏洞

一&#xff0c;工具及环境准备 以下都是超详细保姆级安装教程&#xff0c;缺什么安装什么即可&#xff08;提供镜像工具资源&#xff09; 1-1 VMware 16.0 安装 【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;提供资源&#xff09;-CSDN博客文章浏览阅读20…

Android Datastore 动态创建与源码解析

涉及到的知识点 1、协程原理---->很好的博客介绍&#xff0c;一个小故事讲明白进程、线程、Kotlin 协程到底啥关系&#xff1f; 2、Channel知识点---->Android—kotlin-Channel超详细讲解 3、Coroutines : CompletableDeferred and structured concurrency 封装的DataS…

动态规划-丑数

** 描述 把只包含质因子2、3和5的数称作丑数&#xff08;Ugly Number&#xff09;。例如6、8都是丑数&#xff0c;但14不是&#xff0c;因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第 n个丑数。 数据范围&#xff1a; 0≤n≤2000 要求&#x…

Mysql数据库 9.SQL语言 查询语句 连接查询、子查询

连接查询 通过查询多张表&#xff0c;用连接查询进行多表联合查询 关键字&#xff1a;inner join 内连接 left join 左连接 right join 右连接 数据准备 创建新的数据库&#xff1a;create database 数据库名; create database db_test2; 使用数据库&#xff1a;use 数据…

企业如何搭建智能客服系统?

在数字化时代&#xff0c;企业面临着客户需求多样化、市场竞争日益激烈等多重挑战。为了更好地满足客户的需求、提供高效的服务&#xff0c;越来越多的企业开始搭建智能客服系统。智能客服系统结合了人工智能和自然语言处理技术&#xff0c;可以实现自动回复、智能推荐以及数据…

Linux内核移植之主频设置

一. Linux内核移植 正点原子 ALPHA开发板已经添加到 Linux内核里面去了&#xff0c;前面文章关于如何添加已经掌握。但是&#xff0c;还有一些驱动的问题需要修改。 正点原子 I.MX6U-ALPHA 开发板所使用的 I.MX6ULL 芯片主频都是 792MHz 的&#xff0c;也就是NXP 官方宣…

MySQL的event的使用方法

MySQL的event的使用方法 一、事件定时策略 1、查看event事件开启状态 SHOW VARIABLES LIKE event_scheduler;如图&#xff0c;Value值 ON&#xff1a;打开&#xff0c;OFF&#xff1a;关闭。 2、设置event事件打开 SET GLOBAL event_scheduler ON;如果MySQL重启了&#x…

Python模块导入出现ModuleNotFoundError: No module named ‘***’解决方法

概述 几年没弄python了&#xff0c;全部还会给老师&#xff0c;今天弄了个demo&#xff0c;老是报错&#xff0c;在此记录下&#xff0c;方便后续查阅。 环境&#xff1a;Windows10 开发IDEA&#xff1a;PyCharm 2023.1.3 1、报错如下所示 2、解决方法&#xff1a;安装execjs…

AJAX-解决回调函数地狱问题

一、同步代码和异步代码 1.同步代码 浏览器是按照我们书写代码的顺序一行一行地执行程序的。浏览器会等待代码的解析和工作&#xff0c;在上一行完成之后才会执行下一行。这也使得它成为一个同步程序。 总结来说&#xff1a;逐行执行&#xff0c;需原地等待结果后&#xff0…

[python 刷题] 437 Path Sum III

[python 刷题] 437 Path Sum III 之前有写过 Path Sum I & II, leetcode 112 & 113&#xff0c;虽然使用 JS 写的&#xff0c;不过 python 的实现也更新了一下 题目如下&#xff1a; Given the root of a binary tree and an integer targetSum, return the number o…

解释一下Node.js中的事件循环(event loop)

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

目前安卓、鸿蒙、澎湃的关系

1、了解AOSP是什么 AOSP全名为Android Open-Source Project&#xff0c;中文为安卓开源项目&#xff0c;开源即开放源代码。Android是一个基于Linux&#xff0c;由Google主导的开源系统。 2、AOSP谁的贡献最大&#xff1f; 3、华为的鸿蒙、小米的澎湃是套壳安卓吗&#xff1…

docker基础用法

docker基础用法 什么是docker docker中的容器&#xff1a; lxc --> libcontainer --> runC OCI Open Container-initiative 由Linux基金会主导于2015年6月创立旨在围绕容器格式和运行时制定一个开放的工业化标准contains two specifications the Runtime Specificat…

类的基本概念

类的概念是为了让程序设计语言能更清楚地描述日常生活中的事物。类是对某一类事物的描述&#xff0c;是抽象的、概念上的定义&#xff1b;而对象则是实际存在的属该类事物的具体个体&#xff0c;因而也称为实例&#xff08;instance&#xff09;。下面用一个现实生活中的例子来…