> ## Documentation Index
> Fetch the complete documentation index at: https://felimet-hub.jmcores.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Publications: schlieren imaging and depth sensing research

> Peer-reviewed journal and conference publications on schlieren optical imaging, depth-based livestock sensing, and machine learning methods.

export const publicationsEn = [{
  "title": "Deep neural network for schlieren quality and artifacts",
  "description": "IEEE DTDA 2025 paper combining blind deconvolution with Conditional GANs to enhance schlieren image quality and remove ghost artifacts in flow visualization.",
  "href": "/en/publications/conference/DtDA2025",
  "tags": ["Schlieren", "Ghost Artifacts", "Blind Deconvolution", "CGANs"],
  "featured": false,
  "order": 6,
  "date": "2025-10-20",
  "pubType": "conference",
  "venue": "2025 IEEE International Conference on Device Technologies for Diversified Applications (IEEE DTDA 2025)",
  "confType": "",
  "award": ""
}, {
  "title": "Traditional vs. Z-type schlieren systems for ML use",
  "description": "ICMLSC 2025 paper comparing standard and Z-configuration schlieren optics, evaluating cutoff ratio effects and their potential for machine learning use.",
  "href": "/en/publications/conference/ICMLSC2025",
  "tags": ["Schlieren", "ML", "Cutoff Ratio", "Z-Configuration"],
  "featured": false,
  "order": 5,
  "date": "2025-01-24",
  "pubType": "conference",
  "venue": "Tokyo, Japan",
  "confType": "",
  "award": ""
}, {
  "title": "Color schlieren thermal imaging for epidemic prevention",
  "description": "Automation 2023 paper using color schlieren and infrared thermal imaging with PIV and RPCA to measure mask exhalation airflow velocity and temperature.",
  "href": "/en/publications/conference/auto2023",
  "tags": ["Schlieren", "PIV", "RPCA", "Thermal Imaging"],
  "featured": false,
  "order": 1,
  "date": "2023-12-08",
  "pubType": "conference",
  "venue": "The 20th International Conference on Automation Technology (Automation 2023)",
  "confType": "Oral",
  "award": ""
}, {
  "title": "Causal analysis of temperature heterogeneity on airflow",
  "description": "Automation 2024 paper combining color schlieren, infrared thermal imaging, DCP/NLIDA dehazing, and causal decomposition to study temperature effects on airflow.",
  "href": "/en/publications/conference/auto2024",
  "tags": ["Schlieren", "Thermal Imaging", "Causal Analysis", "Image Dehazing", "Clustering Analysis"],
  "featured": false,
  "order": 2,
  "date": "2024-11-22",
  "pubType": "conference",
  "venue": "The 21th International Conference on Automation Technology (Automation 2024)",
  "confType": "Oral",
  "award": "Best Student Paper Award 2nd Place"
}, {
  "title": "Water pollution analysis with GLCM and schlieren imaging",
  "description": "Automation 2025 paper integrating Z-type schlieren, near-infrared spectroscopy, and GLCM texture features to build a turbidity model for water pollution.",
  "href": "/en/publications/conference/auto2025",
  "tags": ["Schlieren", "GLCM", "Turbidity prediction"],
  "featured": false,
  "order": 3,
  "date": "2025-11-28",
  "pubType": "conference",
  "venue": "The 22th International Conference on Automation Technology (Automation 2025)",
  "confType": "Oral",
  "award": ""
}, {
  "title": "Dairy cattle weight estimation from rump depth images",
  "description": "Biomechatronics 2024 paper predicting dairy cattle body weight from rump depth images via image processing and feedforward networks: non-contact weighing.",
  "href": "/en/publications/conference/biomech2024",
  "tags": ["Depth Image", "Machine Learning", "Regression Analysis", "Dairy Cattle"],
  "featured": false,
  "order": 4,
  "date": "2024-10-24",
  "pubType": "conference",
  "venue": "2024 Conference on Agricultural Machinery and Bio-Mechatronics Engineering",
  "confType": "",
  "award": ""
}, {
  "title": "Holstein dairy cow weight prediction with depth sensing",
  "description": "Biosystems Engineering paper using Intel RealSense D455 depth sensing and Gaussian Process Regression to predict Holstein cow weight across postpartum stages.",
  "href": "/en/publications/journal/dairycow_Biosystems_j1",
  "tags": ["Depth Sensing", "GPR", "ML", "Dairy Cow"],
  "featured": false,
  "order": 3,
  "date": "2025-09-11",
  "pubType": "journal",
  "venue": "Biosystems Engineering",
  "confType": "",
  "award": ""
}, {
  "title": "Dynamic color schlieren system for airflow and temperature",
  "description": "IEEE Trans. Computational Imaging paper: low-cost dynamic color schlieren system with FNN to visualize airflow and predict temperature from color distribution.",
  "href": "/en/publications/journal/schlieren_IEEE_j1",
  "tags": ["Schlieren", "FNN", "Image Dehazing", "MATLAB NNFit"],
  "featured": false,
  "order": 1,
  "date": "2024-02-15",
  "pubType": "journal",
  "venue": "IEEE Transactions on Computational Imaging",
  "confType": "",
  "award": ""
}, {
  "title": "Dynamic color schlieren for airflow velocity prediction",
  "description": "IEEE Sensors Journal paper using dynamic color schlieren, four-quadrant color filters, and an NIO time-series network to predict low-speed airflow velocity.",
  "href": "/en/publications/journal/schlieren_IEEE_j2",
  "tags": ["Schlieren", "Velocity Prediction", "NIO Network", "Optical Sensors"],
  "featured": false,
  "order": 2,
  "date": "2024-11-28",
  "pubType": "journal",
  "venue": "IEEE Sensors Journal",
  "confType": "",
  "award": ""
}];

export const Gallery = ({items = [], type = "projects", lang = "zh"}) => {
  const TAG_LIMIT = 12;
  const t = lang === "en" ? {
    all: "All",
    more: n => `+${n} more`,
    less: "Show less",
    filter: "Filter",
    unit: n => `${n} items`,
    featured: "Featured first",
    date: "Newest first",
    title: "Title A→Z"
  } : {
    all: "全部",
    more: n => `+${n} 更多`,
    less: "收起",
    filter: "篩選",
    unit: n => `${n} 篇`,
    featured: "精選優先",
    date: "日期新→舊",
    title: "標題 A→Z"
  };
  const toTags = v => Array.isArray(v) ? v : typeof v === "string" && v.trim().startsWith("[") ? (() => {
    try {
      return JSON.parse(v);
    } catch {
      return [];
    }
  })() : v ? [String(v)] : [];
  const tagCount = {};
  for (const it of items) for (const tg of toTags(it.tags)) tagCount[tg] = (tagCount[tg] || 0) + 1;
  const sortedTags = Object.keys(tagCount).sort((a, b) => tagCount[b] - tagCount[a]);
  const [tag, setTag] = useState("all");
  const [sort, setSort] = useState(type === "publications" ? "date" : "featured");
  const [showAllTags, setShowAllTags] = useState(false);
  const visibleTags = showAllTags ? sortedTags : sortedTags.slice(0, TAG_LIMIT);
  const filtered = tag === "all" ? items : items.filter(i => toTags(i.tags).includes(tag));
  const shown = [...filtered].sort((a, b) => {
    if (sort === "title") return a.title.localeCompare(b.title, lang === "en" ? "en" : "zh-TW");
    if (sort === "date") return String(b.date).localeCompare(String(a.date));
    return (b.featured ? 1 : 0) - (a.featured ? 1 : 0) || a.order - b.order;
  });
  return <div>
      <div style={{
    marginBottom: "1.75rem"
  }}>
        <div style={{
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
    marginBottom: "0.6rem"
  }}>
          <span className="g-filter-label">{t.filter} · {t.unit(shown.length)}</span>
          <select className="g-sort" value={sort} onChange={e => setSort(e.target.value)}>
            <option value="featured">{t.featured}</option>
            <option value="date">{t.date}</option>
            <option value="title">{t.title}</option>
          </select>
        </div>
        <div style={{
    display: "flex",
    flexWrap: "wrap",
    gap: "0.4rem",
    alignItems: "center"
  }}>
          <button className={"g-chip" + (tag === "all" ? " g-chip-on" : "")} onClick={() => setTag("all")}>{t.all}</button>
          {visibleTags.map(tg => <button key={tg} className={"g-chip" + (tag === tg ? " g-chip-on" : "")} onClick={() => setTag(tg)}>{tg}</button>)}
          {sortedTags.length > TAG_LIMIT && <button className="g-more" onClick={() => setShowAllTags(!showAllTags)}>
              {showAllTags ? t.less : t.more(sortedTags.length - TAG_LIMIT)}
            </button>}
        </div>
      </div>

      <div style={{
    display: "grid",
    gridTemplateColumns: "repeat(auto-fill, minmax(290px, 1fr))",
    gap: "1rem"
  }}>
        {shown.map(i => {
    const tags = toTags(i.tags);
    return <a key={i.href} href={i.href} className="g-card">
              <div className="g-card-title">
                {i.featured && <span style={{
      color: "#bf7551",
      marginRight: "0.3rem"
    }}>★</span>}
                {i.title}
              </div>
              <div className="g-card-desc">
                {i.description.length > 88 ? i.description.slice(0, 88) + "…" : i.description}
              </div>
              {(i.venue || tags.length > 0) && <div className="g-card-meta">
                  {i.venue && <div className="g-card-venue">{i.venue}</div>}
                  <div style={{
      display: "flex",
      flexWrap: "wrap",
      gap: "0.3rem"
    }}>
                    {tags.slice(0, 3).map(tg => <span key={tg} className="g-tag">{tg}</span>)}
                    {tags.length > 3 && <span className="g-tag-more">+{tags.length - 3}</span>}
                  </div>
                </div>}
            </a>;
  })}
      </div>
    </div>;
};

<Gallery items={publicationsEn} type="publications" lang="en" />
