Chuyển đến nội dung chính

第 6 課:AI 圖案與紡織品設計 — 無縫圖案、調色盤 AI 與織物模擬

利用 AI 無縫生成圖案、調色板提取(CLIP + K-means)、織物模擬、顏色匹配、重複圖案類型、紡織品特定約束、Pantone/色域映射。

🏗️ 建築 — 第 6 課 第 6 課:AI 圖案與紡織品設計 — 無縫圖案、調色盤 AI & 布料模擬

時裝設計與按需印刷系統架構-從領域分析到生產

第 2 部分:人工智慧驅動的設計工作室

亞洲開發網

1. AI無縫圖案生成

POD時尚中的紡織品設計需要 無縫模式 — 圖案在整個織物表面無縫重複,沒有明顯的接縫。

Pattern Types trong Textile Design
┌──────────────────────────────────────────────────────┐
│                                                      │
│  Block Repeat     Half-Drop        Brick Repeat      │
│  ┌──┬──┬──┐      ┌──┬──┬──┐      ┌──┬──┬──┐        │
│  │A │A │A │      │A │A │A │      │AABB│AA│          │
│  ├──┼──┼──┤      │ A│ A│ A│      ├──┼──┼──┤         │
│  │A │A │A │      │A │A │A │      │BB│AABB│          │
│  ├──┼──┼──┤      │ A│ A│ A│      ├──┼──┼──┤         │
│  │A │A │A │      │A │A │A │      │AABB│AA│          │
│  └──┴──┴──┘      └──┴──┴──┘      └──┴──┴──┘        │
│                                                      │
│  Mirror           Diamond         Ogee               │
│  ┌──┬──┬──┐      ┌──────┐        ┌──────┐           │
│  │A │A▮│A │      │ /\ /\│        │)(  )(│           │
│  │  │  │  │      │/  X  \│       │(    (│           │
│  │A▮│A │A▮│      │\  X  /│       │)(  )(│           │
│  └──┴──┴──┘      │ \/  \/│       └──────┘           │
│                   └──────┘                           │
└──────────────────────────────────────────────────────┘

2. AI 模式生成流程

interface PatternGenerationRequest {
  prompt: string;                    // "tropical leaves, monstera"
  repeatType: RepeatType;
  tileSize: { width: number; height: number };  // px at target DPI
  colorPalette?: string[];
  density: 'sparse' | 'medium' | 'dense';
  style: 'photorealistic' | 'watercolor' | 'flat' | 'hand_drawn' | 'geometric';
}

type RepeatType = 'block' | 'half_drop' | 'brick' | 'mirror' | 'diamond' | 'random';

// Step 1: Generate base tile with SDXL + tiling ControlNet
async function generatePatternTile(req: PatternGenerationRequest): Promise<Buffer> {
  const prompt = buildPatternPrompt(req);
  
  // Sử dụng SDXL + Tile ControlNet để tạo seamless tile
  const result = await sdxlPipeline.generate({
    prompt: prompt.positive,
    negative_prompt: prompt.negative + ', visible seam, edge artifact, asymmetric',
    width: req.tileSize.width,
    height: req.tileSize.height,
    num_inference_steps: 40,
    guidance_scale: 8.0,
    controlnet: {
      model: 'tile',
      // Tile padding technique: pad image edges to ensure seamless
      preprocessor: 'tile_resample',
    },
  });

  return result.images[0];
}

// Step 2: Post-process for perfect seamless tiling
async function makeSeamless(tile: Buffer): Promise<Buffer> {
  // Technique: Cross-blend edges
  // 1. Pad tile by 25% on each edge (wrapping around)
  // 2. Inpaint the seam areas using SDXL inpainting
  // 3. Crop back to original size
  
  const padded = await padTileWithWrap(tile, 0.25);
  const seamMask = generateSeamMask(padded, 0.25);
  
  const inpainted = await sdxlInpaint({
    image: padded,
    mask: seamMask,
    prompt: 'seamless continuation, consistent style and color',
    strength: 0.6,  // Chỉ blend nhẹ phần seam
  });

  return cropToOriginal(inpainted, 0.25);
}

3. 調色板AI

// Color palette extraction và generation
interface ColorPaletteService {
  // Extract palette from image
  extractFromImage(image: Buffer, numColors: number): Promise<ColorPalette>;
  
  // Generate harmonious palette from seed color
  generateHarmonious(seedColor: string, harmony: ColorHarmony): ColorPalette;
  
  // AI-suggested palette from text/mood
  suggestFromMood(mood: string): Promise<ColorPalette[]>;
  
  // Map RGB to nearest Pantone
  mapToPantone(color: string): PantoneColor;
  
  // Check printability (is color within CMYK gamut?)
  checkGamut(color: string, printMethod: string): GamutResult;
}

interface ColorPalette {
  id: string;
  name: string;
  colors: PaletteColor[];
  mood: string[];           // ['tropical', 'warm', 'energetic']
  season: string[];         // ['summer', 'spring']
}

interface PaletteColor {
  hex: string;
  rgb: { r: number; g: number; b: number };
  cmyk: { c: number; m: number; y: number; k: number };
  pantone?: string;         // 'PANTONE 18-1664 TCX'
  name: string;             // 'Fiery Red'
  percentage: number;       // Tỷ lệ trong palette
}

type ColorHarmony = 
  | 'complementary'         // Đối diện trên color wheel
  | 'analogous'             // Liền kề
  | 'triadic'               // Tam giác  
  | 'split_complementary'   // Bổ sung chia
  | 'tetradic'              // Tứ giác
  | 'monochromatic';        // Đơn sắc

// K-Means color extraction
async function extractDominantColors(
  image: Buffer, 
  k: number = 5,
): Promise<PaletteColor[]> {
  // 1. Resize image to 256x256 for speed
  const resized = await sharp(image).resize(256, 256).raw().toBuffer();
  
  // 2. Convert pixels to LAB color space (perceptually uniform)
  const labPixels = rgbToLab(resized);
  
  // 3. K-Means clustering
  const clusters = kMeansClustering(labPixels, k, {
    maxIterations: 100,
    tolerance: 0.01,
  });

  // 4. Sort by cluster size (most dominant first)
  return clusters
    .sort((a, b) => b.size - a.size)
    .map(cluster => ({
      hex: labToHex(cluster.center),
      rgb: labToRgb(cluster.center),
      cmyk: rgbToCmyk(labToRgb(cluster.center)),
      name: findNearestColorName(cluster.center),
      percentage: cluster.size / labPixels.length,
    }));
}

4. 色域與列印色彩管理

// Kiểm tra color có in được không (CMYK gamut)
interface GamutResult {
  inGamut: boolean;
  originalColor: string;
  printableColor: string;     // Nearest in-gamut color
  deltaE: number;             // Color difference (< 2 = imperceptible)
  warning: string | null;
}

function checkPrintGamut(hexColor: string, printMethod: string): GamutResult {
  const rgb = hexToRgb(hexColor);
  const cmyk = rgbToCmyk(rgb);
  const backToRgb = cmykToRgb(cmyk);
  const deltaE = calculateDeltaE2000(rgb, backToRgb);

  // Neon/fluorescent colors thường ngoài CMYK gamut
  const inGamut = deltaE < 3.0;

  return {
    inGamut,
    originalColor: hexColor,
    printableColor: inGamut ? hexColor : rgbToHex(backToRgb),
    deltaE,
    warning: inGamut ? null : `Color shifts ${deltaE.toFixed(1)}ΔE when printed. Consider using spot color (Pantone).`,
  };
}

// Spot color recommendations cho bright/neon designs
const SPOT_COLOR_ALTERNATIVES: Record<string, string> = {
  '#00ff00': 'PANTONE 802 C',      // Neon Green
  '#ff00ff': 'PANTONE 807 C',      // Neon Magenta
  '#ffff00': 'PANTONE 803 C',      // Neon Yellow
  '#ff6600': 'PANTONE 804 C',      // Neon Orange
  '#ff0066': 'PANTONE 806 C',      // Neon Pink
};

5. 布料模擬

// Mô phỏng pattern trên fabric thực tế
interface FabricSimulator {
  // Render pattern trên fabric với wrinkles, lighting
  simulate(
    pattern: Buffer,
    fabric: FabricType,
    lighting: LightingPreset,
  ): Promise<Buffer>;
}

interface FabricType {
  name: string;          // 'cotton_jersey', 'polyester', 'silk', 'denim'
  texture: string;       // Normal map URL
  roughness: number;     // 0.0 (silk) - 1.0 (canvas)
  stretch: number;       // 0.0 (denim) - 1.0 (spandex)
  opacity: number;       // Fabric opacity (sublimation bleeds differently)
  weavePattern?: string; // Weave texture overlay
}

type LightingPreset = 'studio' | 'natural' | 'dramatic' | 'flat';

// Fabric presets for common POD products
const FABRIC_PRESETS: Record<string, FabricType> = {
  cotton_jersey: {
    name: 'Cotton Jersey (T-shirt)',
    texture: '/textures/cotton-jersey-normal.png',
    roughness: 0.7,
    stretch: 0.3,
    opacity: 1.0,
  },
  polyester_performance: {
    name: 'Polyester (All-over print)',
    texture: '/textures/polyester-smooth-normal.png',
    roughness: 0.3,
    stretch: 0.5,
    opacity: 0.95,   // Sublimation shows fabric texture slightly
  },
  canvas_tote: {
    name: 'Canvas (Tote bag)',
    texture: '/textures/canvas-weave-normal.png',
    roughness: 0.9,
    stretch: 0.05,
    opacity: 1.0,
    weavePattern: '/textures/canvas-weave-overlay.png',
  },
};

6. 模式重複引擎

// Engine tạo các loại repeat từ single tile
function applyRepeat(
  tile: Buffer,
  repeatType: RepeatType,
  gridSize: { cols: number; rows: number },
): Promise<Buffer> {
  switch (repeatType) {
    case 'block':
      // Simple tile repeat - A A A / A A A
      return tileRepeat(tile, gridSize);

    case 'half_drop':
      // Offset 50% vertically mỗi column
      return halfDropRepeat(tile, gridSize);

    case 'brick':
      // Offset 50% horizontally mỗi row (like brick wall)
      return brickRepeat(tile, gridSize);

    case 'mirror':
      // Flip alternating tiles (kaleidoscope effect)
      return mirrorRepeat(tile, gridSize);

    case 'diamond':
      // Rotate 45° and tile trong diamond grid
      return diamondRepeat(tile, gridSize);

    case 'random':
      // Random rotation + scale variations
      return randomScatterRepeat(tile, gridSize, {
        rotationRange: [-15, 15],    // degrees
        scaleRange: [0.8, 1.2],
        overlapAllowed: true,
      });
  }
}

// Validate seamlessness after repeat
async function validateSeamless(
  pattern: Buffer,
  tolerance: number = 5, // pixel difference threshold
): Promise<SeamValidationResult> {
  const { width, height } = await sharp(pattern).metadata();
  
  // Check horizontal seam: compare right edge of tile N with left edge of tile N+1
  const leftEdge = await extractColumn(pattern, 0);
  const rightEdge = await extractColumn(pattern, width! - 1);
  
  // Check vertical seam
  const topEdge = await extractRow(pattern, 0);
  const bottomEdge = await extractRow(pattern, height! - 1);

  const hDiff = calculateEdgeDifference(rightEdge, leftEdge);
  const vDiff = calculateEdgeDifference(bottomEdge, topEdge);

  return {
    seamless: hDiff < tolerance && vDiff < tolerance,
    horizontalDifference: hDiff,
    verticalDifference: vDiff,
    suggestion: hDiff >= tolerance || vDiff >= tolerance
      ? 'Seam detected. Re-running inpaint blending on edges.'
      : null,
  };
}

七、總結

組件科技使用案例
模式生成SDXL + Tile ControlNetCreate seamless tiles from text prompt
接縫固定修復交叉混合去除磁磚之間的接縫
顏色提取LAB 空間中的 K 均值照片中的主色調
色彩和諧色輪演算法建議調色板和諧
色域檢查RGB↔CMYK Delta-E 2000檢查是否可以印在布料上
潘通映射最近鄰 LAB映射到標準專色
布料模擬法線貼圖+PBR渲染在真實織物上預覽圖案
重複引擎平鋪變換+驗證6 種模式重複類型