123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553 |
- import { Injectable } from '@angular/core';
- import { Observable, of } from 'rxjs';
- // 纹理分析结果接口
- export interface PatternAnalysisResult {
- patternRecognition: PatternRecognition;
- repetitionAnalysis: RepetitionAnalysis;
- textureClassification: TextureClassification;
- visualRhythm: VisualRhythm;
- designRecommendations: string[];
- }
- // 图案识别
- export interface PatternRecognition {
- primaryPatterns: Array<{
- type: 'geometric' | 'organic' | 'abstract' | 'floral' | 'striped' | 'checkered' | 'dotted' | 'textured';
- confidence: number; // 0-100
- coverage: number; // 0-100
- characteristics: string[];
- }>;
- patternComplexity: {
- level: 'simple' | 'moderate' | 'complex' | 'very-complex';
- score: number; // 0-100
- elements: number; // 图案元素数量
- };
- patternScale: {
- size: 'micro' | 'small' | 'medium' | 'large' | 'macro';
- uniformity: number; // 0-100
- variation: number; // 0-100
- };
- }
- // 重复性分析
- export interface RepetitionAnalysis {
- repetitionType: {
- primary: 'regular' | 'irregular' | 'random' | 'semi-regular';
- pattern: 'grid' | 'brick' | 'hexagonal' | 'radial' | 'linear' | 'organic';
- consistency: number; // 0-100
- };
- spacing: {
- horizontal: number; // 像素或相对单位
- vertical: number;
- uniformity: number; // 0-100
- rhythm: 'tight' | 'moderate' | 'loose' | 'varied';
- };
- symmetry: {
- type: 'bilateral' | 'radial' | 'translational' | 'rotational' | 'none';
- strength: number; // 0-100
- axes: number; // 对称轴数量
- };
- tiling: {
- seamless: boolean;
- quality: number; // 0-100
- edgeHandling: 'perfect' | 'good' | 'fair' | 'poor';
- };
- }
- // 纹理分类
- export interface TextureClassification {
- textureFamily: {
- primary: 'natural' | 'artificial' | 'hybrid';
- subcategory: string;
- confidence: number; // 0-100
- };
- surfaceCharacter: {
- tactileQuality: 'smooth' | 'rough' | 'bumpy' | 'ridged' | 'woven' | 'carved';
- visualDepth: number; // 0-100
- dimensionality: '2D' | '2.5D' | '3D';
- };
- materialSuggestion: {
- likelyMaterials: string[];
- fabricationMethod: string[];
- applicationSuitability: string[];
- };
- }
- // 视觉节奏
- export interface VisualRhythm {
- rhythmType: {
- primary: 'regular' | 'alternating' | 'flowing' | 'progressive' | 'random';
- intensity: number; // 0-100
- tempo: 'slow' | 'moderate' | 'fast' | 'varied';
- };
- movement: {
- direction: 'horizontal' | 'vertical' | 'diagonal' | 'radial' | 'multi-directional';
- flow: number; // 0-100
- energy: number; // 0-100
- };
- emphasis: {
- focalPoints: number;
- contrast: number; // 0-100
- hierarchy: number; // 0-100
- };
- harmony: {
- overall: number; // 0-100
- balance: number; // 0-100
- unity: number; // 0-100
- };
- }
- @Injectable({
- providedIn: 'root'
- })
- export class PatternAnalysisService {
- constructor() { }
- /**
- * 分析图片中的纹理图案
- * @param imageFile 图片文件
- */
- analyzeImagePattern(imageFile: File): Observable<PatternAnalysisResult> {
- return of(this.simulatePatternAnalysis(imageFile));
- }
- /**
- * 分析URL图片的纹理图案
- * @param imageUrl 图片URL
- */
- analyzePatternFromUrl(imageUrl: string): Observable<PatternAnalysisResult> {
- return of(this.simulatePatternAnalysisFromUrl(imageUrl));
- }
- /**
- * 模拟纹理图案分析
- */
- private simulatePatternAnalysis(imageFile: File): PatternAnalysisResult {
- const fileName = imageFile.name.toLowerCase();
- return this.generatePatternAnalysis(fileName);
- }
- private simulatePatternAnalysisFromUrl(imageUrl: string): PatternAnalysisResult {
- const urlLower = imageUrl.toLowerCase();
- return this.generatePatternAnalysis(urlLower);
- }
- private generatePatternAnalysis(context: string): PatternAnalysisResult {
- const patternType = this.inferPatternType(context);
-
- return {
- patternRecognition: this.generatePatternRecognition(patternType, context),
- repetitionAnalysis: this.generateRepetitionAnalysis(patternType, context),
- textureClassification: this.generateTextureClassification(patternType, context),
- visualRhythm: this.generateVisualRhythm(patternType, context),
- designRecommendations: this.generateDesignRecommendations(patternType, context)
- };
- }
- private inferPatternType(context: string): string {
- if (context.includes('geometric') || context.includes('grid')) return 'geometric';
- if (context.includes('floral') || context.includes('flower')) return 'floral';
- if (context.includes('stripe') || context.includes('line')) return 'striped';
- if (context.includes('dot') || context.includes('circle')) return 'dotted';
- if (context.includes('check') || context.includes('square')) return 'checkered';
- if (context.includes('organic') || context.includes('natural')) return 'organic';
- if (context.includes('abstract')) return 'abstract';
- return 'textured'; // 默认纹理类型
- }
- private generatePatternRecognition(patternType: string, context: string): PatternRecognition {
- const isComplex = context.includes('complex') || context.includes('detailed');
- const isLarge = context.includes('large') || context.includes('big');
-
- const basePattern = this.getBasePatternData(patternType);
-
- return {
- primaryPatterns: [
- {
- type: patternType as any,
- confidence: 85 + Math.random() * 10,
- coverage: 70 + Math.random() * 25,
- characteristics: basePattern.characteristics
- }
- ],
- patternComplexity: {
- level: isComplex ? 'complex' : basePattern.complexity.level,
- score: isComplex ? 80 + Math.random() * 15 : basePattern.complexity.score,
- elements: isComplex ? 15 + Math.floor(Math.random() * 10) : basePattern.complexity.elements
- },
- patternScale: {
- size: isLarge ? 'large' : basePattern.scale.size,
- uniformity: basePattern.scale.uniformity,
- variation: basePattern.scale.variation
- }
- };
- }
- private getBasePatternData(patternType: string): any {
- const patterns: { [key: string]: any } = {
- geometric: {
- characteristics: ['规则', '对称', '数学性', '现代'],
- complexity: { level: 'moderate', score: 60, elements: 8 },
- scale: { size: 'medium', uniformity: 85, variation: 20 }
- },
- floral: {
- characteristics: ['自然', '有机', '装饰性', '传统'],
- complexity: { level: 'complex', score: 75, elements: 12 },
- scale: { size: 'medium', uniformity: 60, variation: 40 }
- },
- striped: {
- characteristics: ['线性', '方向性', '简洁', '经典'],
- complexity: { level: 'simple', score: 30, elements: 3 },
- scale: { size: 'medium', uniformity: 90, variation: 15 }
- },
- dotted: {
- characteristics: ['点状', '规律', '轻盈', '现代'],
- complexity: { level: 'simple', score: 35, elements: 4 },
- scale: { size: 'small', uniformity: 80, variation: 25 }
- },
- checkered: {
- characteristics: ['格子', '对比', '经典', '结构化'],
- complexity: { level: 'simple', score: 40, elements: 2 },
- scale: { size: 'medium', uniformity: 95, variation: 10 }
- },
- organic: {
- characteristics: ['自然', '流动', '不规则', '和谐'],
- complexity: { level: 'moderate', score: 65, elements: 10 },
- scale: { size: 'varied', uniformity: 45, variation: 60 }
- },
- abstract: {
- characteristics: ['抽象', '艺术性', '创新', '表现力'],
- complexity: { level: 'complex', score: 80, elements: 15 },
- scale: { size: 'varied', uniformity: 40, variation: 70 }
- },
- textured: {
- characteristics: ['质感', '触觉', '深度', '材质感'],
- complexity: { level: 'moderate', score: 55, elements: 6 },
- scale: { size: 'small', uniformity: 70, variation: 35 }
- }
- };
- return patterns[patternType] || patterns['textured'];
- }
- private generateRepetitionAnalysis(patternType: string, context: string): RepetitionAnalysis {
- const isRegular = patternType === 'geometric' || patternType === 'striped' || patternType === 'checkered';
- const isSeamless = context.includes('seamless') || context.includes('tile');
-
- return {
- repetitionType: {
- primary: isRegular ? 'regular' : 'semi-regular',
- pattern: this.getRepetitionPattern(patternType),
- consistency: isRegular ? 85 + Math.random() * 10 : 60 + Math.random() * 25
- },
- spacing: {
- horizontal: 50 + Math.random() * 100,
- vertical: 50 + Math.random() * 100,
- uniformity: isRegular ? 85 + Math.random() * 10 : 55 + Math.random() * 30,
- rhythm: this.getSpacingRhythm(patternType)
- },
- symmetry: {
- type: this.getSymmetryType(patternType),
- strength: this.getSymmetryStrength(patternType),
- axes: this.getSymmetryAxes(patternType)
- },
- tiling: {
- seamless: isSeamless,
- quality: isSeamless ? 90 + Math.random() * 8 : 60 + Math.random() * 30,
- edgeHandling: isSeamless ? 'perfect' : 'good'
- }
- };
- }
- private generateTextureClassification(patternType: string, context: string): TextureClassification {
- const isNatural = patternType === 'organic' || patternType === 'floral' || context.includes('natural');
-
- return {
- textureFamily: {
- primary: isNatural ? 'natural' : 'artificial',
- subcategory: this.getTextureSubcategory(patternType),
- confidence: 80 + Math.random() * 15
- },
- surfaceCharacter: {
- tactileQuality: this.getTactileQuality(patternType),
- visualDepth: this.getVisualDepth(patternType),
- dimensionality: this.getDimensionality(patternType)
- },
- materialSuggestion: {
- likelyMaterials: this.getLikelyMaterials(patternType),
- fabricationMethod: this.getFabricationMethods(patternType),
- applicationSuitability: this.getApplicationSuitability(patternType)
- }
- };
- }
- private generateVisualRhythm(patternType: string, context: string): VisualRhythm {
- const isDynamic = context.includes('dynamic') || context.includes('movement');
-
- return {
- rhythmType: {
- primary: this.getRhythmType(patternType),
- intensity: this.getRhythmIntensity(patternType, isDynamic),
- tempo: this.getRhythmTempo(patternType)
- },
- movement: {
- direction: this.getMovementDirection(patternType),
- flow: this.getFlowValue(patternType),
- energy: isDynamic ? 80 + Math.random() * 15 : 50 + Math.random() * 30
- },
- emphasis: {
- focalPoints: this.getFocalPoints(patternType),
- contrast: this.getContrastValue(patternType),
- hierarchy: this.getHierarchyValue(patternType)
- },
- harmony: {
- overall: 70 + Math.random() * 25,
- balance: this.getBalanceValue(patternType),
- unity: this.getUnityValue(patternType)
- }
- };
- }
- private generateDesignRecommendations(patternType: string, context: string): string[] {
- const recommendations = [];
-
- // 基于图案类型的建议
- switch (patternType) {
- case 'geometric':
- recommendations.push('保持几何图案的精确性和一致性');
- recommendations.push('考虑使用对比色增强视觉效果');
- break;
- case 'floral':
- recommendations.push('平衡花卉图案的复杂度和可读性');
- recommendations.push('注意色彩搭配的自然和谐');
- break;
- case 'striped':
- recommendations.push('控制条纹的宽度比例');
- recommendations.push('注意条纹方向对空间感的影响');
- break;
- case 'organic':
- recommendations.push('保持有机图案的自然流动感');
- recommendations.push('避免过度规则化');
- break;
- }
-
- // 基于上下文的建议
- if (context.includes('interior')) {
- recommendations.push('考虑图案对室内空间感的影响');
- }
- if (context.includes('fabric')) {
- recommendations.push('注意图案的可缝制性和耐用性');
- }
- if (context.includes('wallpaper')) {
- recommendations.push('确保图案的无缝拼接效果');
- }
-
- return recommendations.length > 0 ? recommendations : ['保持图案设计的整体协调性'];
- }
- // 辅助方法
- private getRepetitionPattern(patternType: string): 'grid' | 'brick' | 'hexagonal' | 'radial' | 'linear' | 'organic' {
- const patterns: { [key: string]: 'grid' | 'brick' | 'hexagonal' | 'radial' | 'linear' | 'organic' } = {
- geometric: 'grid', striped: 'linear', checkered: 'grid',
- dotted: 'grid', floral: 'organic', organic: 'organic',
- abstract: 'radial', textured: 'brick'
- };
- return patterns[patternType] || 'grid';
- }
- private getSpacingRhythm(patternType: string): 'tight' | 'moderate' | 'loose' | 'varied' {
- const rhythms: { [key: string]: 'tight' | 'moderate' | 'loose' | 'varied' } = {
- geometric: 'moderate', striped: 'tight', checkered: 'moderate',
- dotted: 'moderate', floral: 'varied', organic: 'varied',
- abstract: 'varied', textured: 'tight'
- };
- return rhythms[patternType] || 'moderate';
- }
- private getSymmetryType(patternType: string): 'bilateral' | 'radial' | 'translational' | 'rotational' | 'none' {
- const types: { [key: string]: 'bilateral' | 'radial' | 'translational' | 'rotational' | 'none' } = {
- geometric: 'bilateral', striped: 'translational', checkered: 'bilateral',
- dotted: 'translational', floral: 'radial', organic: 'none',
- abstract: 'rotational', textured: 'translational'
- };
- return types[patternType] || 'bilateral';
- }
- private getSymmetryStrength(patternType: string): number {
- const strengths: { [key: string]: number } = {
- geometric: 90, striped: 85, checkered: 95, dotted: 80,
- floral: 60, organic: 30, abstract: 50, textured: 70
- };
- return (strengths[patternType] || 70) + Math.random() * 10;
- }
- private getSymmetryAxes(patternType: string): number {
- const axes: { [key: string]: number } = {
- geometric: 2, striped: 1, checkered: 2, dotted: 4,
- floral: 4, organic: 0, abstract: 3, textured: 1
- };
- return axes[patternType] || 2;
- }
- private getTextureSubcategory(patternType: string): string {
- const subcategories: { [key: string]: string } = {
- geometric: '几何纹理', floral: '植物纹理', striped: '线性纹理',
- dotted: '点状纹理', checkered: '格子纹理', organic: '有机纹理',
- abstract: '抽象纹理', textured: '表面纹理'
- };
- return subcategories[patternType] || '混合纹理';
- }
- private getTactileQuality(patternType: string): 'smooth' | 'rough' | 'bumpy' | 'ridged' | 'woven' | 'carved' {
- const qualities: { [key: string]: 'smooth' | 'rough' | 'bumpy' | 'ridged' | 'woven' | 'carved' } = {
- geometric: 'smooth', floral: 'carved', striped: 'ridged',
- dotted: 'bumpy', checkered: 'woven', organic: 'rough',
- abstract: 'rough', textured: 'rough'
- };
- return qualities[patternType] || 'smooth';
- }
- private getVisualDepth(patternType: string): number {
- const depths: { [key: string]: number } = {
- geometric: 40, floral: 70, striped: 30, dotted: 50,
- checkered: 35, organic: 80, abstract: 85, textured: 90
- };
- return depths[patternType] || 50;
- }
- private getDimensionality(patternType: string): '2D' | '2.5D' | '3D' {
- const dims: { [key: string]: '2D' | '2.5D' | '3D' } = {
- geometric: '2D', floral: '2.5D', striped: '2D', dotted: '2D',
- checkered: '2D', organic: '3D', abstract: '2.5D', textured: '3D'
- };
- return dims[patternType] || '2D';
- }
- private getLikelyMaterials(patternType: string): string[] {
- const materials: { [key: string]: string[] } = {
- geometric: ['金属', '塑料', '陶瓷'],
- floral: ['织物', '壁纸', '陶瓷'],
- striped: ['织物', '木材', '金属'],
- dotted: ['织物', '塑料', '纸张'],
- checkered: ['织物', '瓷砖', '纸张'],
- organic: ['木材', '石材', '皮革'],
- abstract: ['画布', '金属', '玻璃'],
- textured: ['石材', '混凝土', '皮革']
- };
- return materials[patternType] || ['通用材料'];
- }
- private getFabricationMethods(patternType: string): string[] {
- const methods: { [key: string]: string[] } = {
- geometric: ['激光切割', '数控加工', '模具成型'],
- floral: ['印刷', '刺绣', '雕刻'],
- striped: ['编织', '印刷', '切割'],
- dotted: ['打孔', '印刷', '压花'],
- checkered: ['编织', '印刷', '拼接'],
- organic: ['手工雕刻', '铸造', '3D打印'],
- abstract: ['手绘', '喷涂', '数字印刷'],
- textured: ['压花', '喷砂', '化学蚀刻']
- };
- return methods[patternType] || ['常规加工'];
- }
- private getApplicationSuitability(patternType: string): string[] {
- const applications: { [key: string]: string[] } = {
- geometric: ['现代室内', '办公空间', '科技产品'],
- floral: ['家居装饰', '服装设计', '传统空间'],
- striped: ['服装', '室内装饰', '包装设计'],
- dotted: ['儿童用品', '休闲服装', '装饰品'],
- checkered: ['经典服装', '餐厅装饰', '游戏用品'],
- organic: ['自然风格室内', '艺术品', '高端产品'],
- abstract: ['艺术空间', '创意产品', '展示设计'],
- textured: ['建筑外观', '工业设计', '触觉产品']
- };
- return applications[patternType] || ['通用应用'];
- }
- private getRhythmType(patternType: string): 'regular' | 'alternating' | 'flowing' | 'progressive' | 'random' {
- const types: { [key: string]: 'regular' | 'alternating' | 'flowing' | 'progressive' | 'random' } = {
- geometric: 'regular', floral: 'flowing', striped: 'alternating',
- dotted: 'regular', checkered: 'alternating', organic: 'flowing',
- abstract: 'progressive', textured: 'random'
- };
- return types[patternType] || 'regular';
- }
- private getRhythmIntensity(patternType: string, isDynamic: boolean): number {
- const base: { [key: string]: number } = {
- geometric: 60, floral: 70, striped: 80, dotted: 50,
- checkered: 75, organic: 65, abstract: 85, textured: 55
- };
- const intensity = base[patternType] || 60;
- return isDynamic ? Math.min(95, intensity + 20) : intensity;
- }
- private getRhythmTempo(patternType: string): 'slow' | 'moderate' | 'fast' | 'varied' {
- const tempos: { [key: string]: 'slow' | 'moderate' | 'fast' | 'varied' } = {
- geometric: 'moderate', floral: 'slow', striped: 'fast',
- dotted: 'moderate', checkered: 'fast', organic: 'varied',
- abstract: 'varied', textured: 'slow'
- };
- return tempos[patternType] || 'moderate';
- }
- private getMovementDirection(patternType: string): 'horizontal' | 'vertical' | 'diagonal' | 'radial' | 'multi-directional' {
- const directions: { [key: string]: 'horizontal' | 'vertical' | 'diagonal' | 'radial' | 'multi-directional' } = {
- geometric: 'multi-directional', floral: 'radial', striped: 'horizontal',
- dotted: 'multi-directional', checkered: 'multi-directional', organic: 'radial',
- abstract: 'multi-directional', textured: 'multi-directional'
- };
- return directions[patternType] || 'multi-directional';
- }
- private getFlowValue(patternType: string): number {
- const flows: { [key: string]: number } = {
- geometric: 50, floral: 80, striped: 70, dotted: 40,
- checkered: 45, organic: 90, abstract: 75, textured: 60
- };
- return (flows[patternType] || 60) + Math.random() * 15;
- }
- private getFocalPoints(patternType: string): number {
- const points: { [key: string]: number } = {
- geometric: 4, floral: 6, striped: 2, dotted: 8,
- checkered: 4, organic: 3, abstract: 5, textured: 2
- };
- return points[patternType] || 4;
- }
- private getContrastValue(patternType: string): number {
- const contrasts: { [key: string]: number } = {
- geometric: 80, floral: 60, striped: 90, dotted: 70,
- checkered: 95, organic: 50, abstract: 85, textured: 65
- };
- return (contrasts[patternType] || 70) + Math.random() * 15;
- }
- private getHierarchyValue(patternType: string): number {
- const hierarchies: { [key: string]: number } = {
- geometric: 85, floral: 70, striped: 60, dotted: 55,
- checkered: 75, organic: 65, abstract: 80, textured: 50
- };
- return (hierarchies[patternType] || 65) + Math.random() * 15;
- }
- private getBalanceValue(patternType: string): number {
- const balances: { [key: string]: number } = {
- geometric: 90, floral: 75, striped: 85, dotted: 80,
- checkered: 95, organic: 60, abstract: 70, textured: 65
- };
- return (balances[patternType] || 75) + Math.random() * 15;
- }
- private getUnityValue(patternType: string): number {
- const unities: { [key: string]: number } = {
- geometric: 85, floral: 80, striped: 90, dotted: 75,
- checkered: 90, organic: 70, abstract: 65, textured: 70
- };
- return (unities[patternType] || 75) + Math.random() * 15;
- }
- }
|