warpAffine 是图像处理中比较常见的一种变换,可以将图像校正或对齐。

对于线性插值方式,OpenCV 首先将坐标映射保存成两张图,然后调用 remap 函数。第二步是比较耗时的部分,并且 warpPerspective 亦采用此处理。

remap 通过构建查找表来存储系数乘积,这样减少了乘法运算次数。

由于篇幅过长,将文章分成 warpAffine 和 remap 两部分。

#mermaid-svg-9sdnp2DyaSJ0w3si .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .label text{fill:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .node rect,#mermaid-svg-9sdnp2DyaSJ0w3si .node circle,#mermaid-svg-9sdnp2DyaSJ0w3si .node ellipse,#mermaid-svg-9sdnp2DyaSJ0w3si .node polygon,#mermaid-svg-9sdnp2DyaSJ0w3si .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-9sdnp2DyaSJ0w3si .node .label{text-align:center;fill:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .node.clickable{cursor:pointer}#mermaid-svg-9sdnp2DyaSJ0w3si .arrowheadPath{fill:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-9sdnp2DyaSJ0w3si .flowchart-link{stroke:#333;fill:none}#mermaid-svg-9sdnp2DyaSJ0w3si .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-9sdnp2DyaSJ0w3si .edgeLabel rect{opacity:0.9}#mermaid-svg-9sdnp2DyaSJ0w3si .edgeLabel span{color:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-9sdnp2DyaSJ0w3si .cluster text{fill:#333}#mermaid-svg-9sdnp2DyaSJ0w3si div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-9sdnp2DyaSJ0w3si .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-9sdnp2DyaSJ0w3si text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-9sdnp2DyaSJ0w3si .actor-line{stroke:grey}#mermaid-svg-9sdnp2DyaSJ0w3si .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-9sdnp2DyaSJ0w3si #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .sequenceNumber{fill:#fff}#mermaid-svg-9sdnp2DyaSJ0w3si #sequencenumber{fill:#333}#mermaid-svg-9sdnp2DyaSJ0w3si #crosshead path{fill:#333;stroke:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .messageText{fill:#333;stroke:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-9sdnp2DyaSJ0w3si .labelText,#mermaid-svg-9sdnp2DyaSJ0w3si .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-9sdnp2DyaSJ0w3si .loopText,#mermaid-svg-9sdnp2DyaSJ0w3si .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-9sdnp2DyaSJ0w3si .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-9sdnp2DyaSJ0w3si .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-9sdnp2DyaSJ0w3si .noteText,#mermaid-svg-9sdnp2DyaSJ0w3si .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-9sdnp2DyaSJ0w3si .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-9sdnp2DyaSJ0w3si .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-9sdnp2DyaSJ0w3si .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-9sdnp2DyaSJ0w3si .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-9sdnp2DyaSJ0w3si .section{stroke:none;opacity:0.2}#mermaid-svg-9sdnp2DyaSJ0w3si .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-9sdnp2DyaSJ0w3si .section2{fill:#fff400}#mermaid-svg-9sdnp2DyaSJ0w3si .section1,#mermaid-svg-9sdnp2DyaSJ0w3si .section3{fill:#fff;opacity:0.2}#mermaid-svg-9sdnp2DyaSJ0w3si .sectionTitle0{fill:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .sectionTitle1{fill:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .sectionTitle2{fill:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .sectionTitle3{fill:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-9sdnp2DyaSJ0w3si .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-9sdnp2DyaSJ0w3si .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-9sdnp2DyaSJ0w3si .grid path{stroke-width:0}#mermaid-svg-9sdnp2DyaSJ0w3si .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-9sdnp2DyaSJ0w3si .task{stroke-width:2}#mermaid-svg-9sdnp2DyaSJ0w3si .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-9sdnp2DyaSJ0w3si .taskText:not([font-size]){font-size:11px}#mermaid-svg-9sdnp2DyaSJ0w3si .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-9sdnp2DyaSJ0w3si .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-9sdnp2DyaSJ0w3si .task.clickable{cursor:pointer}#mermaid-svg-9sdnp2DyaSJ0w3si .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-9sdnp2DyaSJ0w3si .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-9sdnp2DyaSJ0w3si .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-9sdnp2DyaSJ0w3si .taskText0,#mermaid-svg-9sdnp2DyaSJ0w3si .taskText1,#mermaid-svg-9sdnp2DyaSJ0w3si .taskText2,#mermaid-svg-9sdnp2DyaSJ0w3si .taskText3{fill:#fff}#mermaid-svg-9sdnp2DyaSJ0w3si .task0,#mermaid-svg-9sdnp2DyaSJ0w3si .task1,#mermaid-svg-9sdnp2DyaSJ0w3si .task2,#mermaid-svg-9sdnp2DyaSJ0w3si .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-9sdnp2DyaSJ0w3si .taskTextOutside0,#mermaid-svg-9sdnp2DyaSJ0w3si .taskTextOutside2{fill:#000}#mermaid-svg-9sdnp2DyaSJ0w3si .taskTextOutside1,#mermaid-svg-9sdnp2DyaSJ0w3si .taskTextOutside3{fill:#000}#mermaid-svg-9sdnp2DyaSJ0w3si .active0,#mermaid-svg-9sdnp2DyaSJ0w3si .active1,#mermaid-svg-9sdnp2DyaSJ0w3si .active2,#mermaid-svg-9sdnp2DyaSJ0w3si .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-9sdnp2DyaSJ0w3si .activeText0,#mermaid-svg-9sdnp2DyaSJ0w3si .activeText1,#mermaid-svg-9sdnp2DyaSJ0w3si .activeText2,#mermaid-svg-9sdnp2DyaSJ0w3si .activeText3{fill:#000 !important}#mermaid-svg-9sdnp2DyaSJ0w3si .done0,#mermaid-svg-9sdnp2DyaSJ0w3si .done1,#mermaid-svg-9sdnp2DyaSJ0w3si .done2,#mermaid-svg-9sdnp2DyaSJ0w3si .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-9sdnp2DyaSJ0w3si .doneText0,#mermaid-svg-9sdnp2DyaSJ0w3si .doneText1,#mermaid-svg-9sdnp2DyaSJ0w3si .doneText2,#mermaid-svg-9sdnp2DyaSJ0w3si .doneText3{fill:#000 !important}#mermaid-svg-9sdnp2DyaSJ0w3si .crit0,#mermaid-svg-9sdnp2DyaSJ0w3si .crit1,#mermaid-svg-9sdnp2DyaSJ0w3si .crit2,#mermaid-svg-9sdnp2DyaSJ0w3si .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-9sdnp2DyaSJ0w3si .activeCrit0,#mermaid-svg-9sdnp2DyaSJ0w3si .activeCrit1,#mermaid-svg-9sdnp2DyaSJ0w3si .activeCrit2,#mermaid-svg-9sdnp2DyaSJ0w3si .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-9sdnp2DyaSJ0w3si .doneCrit0,#mermaid-svg-9sdnp2DyaSJ0w3si .doneCrit1,#mermaid-svg-9sdnp2DyaSJ0w3si .doneCrit2,#mermaid-svg-9sdnp2DyaSJ0w3si .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-9sdnp2DyaSJ0w3si .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-9sdnp2DyaSJ0w3si .milestoneText{font-style:italic}#mermaid-svg-9sdnp2DyaSJ0w3si .doneCritText0,#mermaid-svg-9sdnp2DyaSJ0w3si .doneCritText1,#mermaid-svg-9sdnp2DyaSJ0w3si .doneCritText2,#mermaid-svg-9sdnp2DyaSJ0w3si .doneCritText3{fill:#000 !important}#mermaid-svg-9sdnp2DyaSJ0w3si .activeCritText0,#mermaid-svg-9sdnp2DyaSJ0w3si .activeCritText1,#mermaid-svg-9sdnp2DyaSJ0w3si .activeCritText2,#mermaid-svg-9sdnp2DyaSJ0w3si .activeCritText3{fill:#000 !important}#mermaid-svg-9sdnp2DyaSJ0w3si .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-9sdnp2DyaSJ0w3si g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-9sdnp2DyaSJ0w3si g.classGroup text .title{font-weight:bolder}#mermaid-svg-9sdnp2DyaSJ0w3si g.clickable{cursor:pointer}#mermaid-svg-9sdnp2DyaSJ0w3si g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-9sdnp2DyaSJ0w3si g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-9sdnp2DyaSJ0w3si .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-9sdnp2DyaSJ0w3si .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-9sdnp2DyaSJ0w3si .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-9sdnp2DyaSJ0w3si .dashed-line{stroke-dasharray:3}#mermaid-svg-9sdnp2DyaSJ0w3si #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-9sdnp2DyaSJ0w3si #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-9sdnp2DyaSJ0w3si #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-9sdnp2DyaSJ0w3si #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-9sdnp2DyaSJ0w3si #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-9sdnp2DyaSJ0w3si #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-9sdnp2DyaSJ0w3si #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-9sdnp2DyaSJ0w3si #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-9sdnp2DyaSJ0w3si .commit-id,#mermaid-svg-9sdnp2DyaSJ0w3si .commit-msg,#mermaid-svg-9sdnp2DyaSJ0w3si .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-9sdnp2DyaSJ0w3si .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-9sdnp2DyaSJ0w3si .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-9sdnp2DyaSJ0w3si g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-9sdnp2DyaSJ0w3si g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-9sdnp2DyaSJ0w3si g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-9sdnp2DyaSJ0w3si g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-9sdnp2DyaSJ0w3si g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-9sdnp2DyaSJ0w3si g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-9sdnp2DyaSJ0w3si .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-9sdnp2DyaSJ0w3si .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-9sdnp2DyaSJ0w3si .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-9sdnp2DyaSJ0w3si .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-9sdnp2DyaSJ0w3si .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-9sdnp2DyaSJ0w3si .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-9sdnp2DyaSJ0w3si .edgeLabel text{fill:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-9sdnp2DyaSJ0w3si .node circle.state-start{fill:black;stroke:black}#mermaid-svg-9sdnp2DyaSJ0w3si .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-9sdnp2DyaSJ0w3si #statediagram-barbEnd{fill:#9370db}#mermaid-svg-9sdnp2DyaSJ0w3si .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-9sdnp2DyaSJ0w3si .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-9sdnp2DyaSJ0w3si .statediagram-state .divider{stroke:#9370db}#mermaid-svg-9sdnp2DyaSJ0w3si .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-9sdnp2DyaSJ0w3si .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-9sdnp2DyaSJ0w3si .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-9sdnp2DyaSJ0w3si .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-9sdnp2DyaSJ0w3si .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-9sdnp2DyaSJ0w3si .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-9sdnp2DyaSJ0w3si .note-edge{stroke-dasharray:5}#mermaid-svg-9sdnp2DyaSJ0w3si .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-9sdnp2DyaSJ0w3si .error-icon{fill:#522}#mermaid-svg-9sdnp2DyaSJ0w3si .error-text{fill:#522;stroke:#522}#mermaid-svg-9sdnp2DyaSJ0w3si .edge-thickness-normal{stroke-width:2px}#mermaid-svg-9sdnp2DyaSJ0w3si .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-9sdnp2DyaSJ0w3si .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-9sdnp2DyaSJ0w3si .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-9sdnp2DyaSJ0w3si .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-9sdnp2DyaSJ0w3si .marker{fill:#333}#mermaid-svg-9sdnp2DyaSJ0w3si .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-9sdnp2DyaSJ0w3si {color: rgba(0, 0, 0, 0.75);font: ;}

warpAffine
remap
WarpPerspective

cv::warpAffine

#mermaid-svg-WoyAl3NPEGyJdv2w .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .label text{fill:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .node rect,#mermaid-svg-WoyAl3NPEGyJdv2w .node circle,#mermaid-svg-WoyAl3NPEGyJdv2w .node ellipse,#mermaid-svg-WoyAl3NPEGyJdv2w .node polygon,#mermaid-svg-WoyAl3NPEGyJdv2w .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-WoyAl3NPEGyJdv2w .node .label{text-align:center;fill:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .node.clickable{cursor:pointer}#mermaid-svg-WoyAl3NPEGyJdv2w .arrowheadPath{fill:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-WoyAl3NPEGyJdv2w .flowchart-link{stroke:#333;fill:none}#mermaid-svg-WoyAl3NPEGyJdv2w .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-WoyAl3NPEGyJdv2w .edgeLabel rect{opacity:0.9}#mermaid-svg-WoyAl3NPEGyJdv2w .edgeLabel span{color:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-WoyAl3NPEGyJdv2w .cluster text{fill:#333}#mermaid-svg-WoyAl3NPEGyJdv2w div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-WoyAl3NPEGyJdv2w .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-WoyAl3NPEGyJdv2w text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-WoyAl3NPEGyJdv2w .actor-line{stroke:grey}#mermaid-svg-WoyAl3NPEGyJdv2w .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-WoyAl3NPEGyJdv2w #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .sequenceNumber{fill:#fff}#mermaid-svg-WoyAl3NPEGyJdv2w #sequencenumber{fill:#333}#mermaid-svg-WoyAl3NPEGyJdv2w #crosshead path{fill:#333;stroke:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .messageText{fill:#333;stroke:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-WoyAl3NPEGyJdv2w .labelText,#mermaid-svg-WoyAl3NPEGyJdv2w .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-WoyAl3NPEGyJdv2w .loopText,#mermaid-svg-WoyAl3NPEGyJdv2w .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-WoyAl3NPEGyJdv2w .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-WoyAl3NPEGyJdv2w .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-WoyAl3NPEGyJdv2w .noteText,#mermaid-svg-WoyAl3NPEGyJdv2w .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-WoyAl3NPEGyJdv2w .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-WoyAl3NPEGyJdv2w .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-WoyAl3NPEGyJdv2w .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-WoyAl3NPEGyJdv2w .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-WoyAl3NPEGyJdv2w .section{stroke:none;opacity:0.2}#mermaid-svg-WoyAl3NPEGyJdv2w .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-WoyAl3NPEGyJdv2w .section2{fill:#fff400}#mermaid-svg-WoyAl3NPEGyJdv2w .section1,#mermaid-svg-WoyAl3NPEGyJdv2w .section3{fill:#fff;opacity:0.2}#mermaid-svg-WoyAl3NPEGyJdv2w .sectionTitle0{fill:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .sectionTitle1{fill:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .sectionTitle2{fill:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .sectionTitle3{fill:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-WoyAl3NPEGyJdv2w .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-WoyAl3NPEGyJdv2w .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-WoyAl3NPEGyJdv2w .grid path{stroke-width:0}#mermaid-svg-WoyAl3NPEGyJdv2w .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-WoyAl3NPEGyJdv2w .task{stroke-width:2}#mermaid-svg-WoyAl3NPEGyJdv2w .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-WoyAl3NPEGyJdv2w .taskText:not([font-size]){font-size:11px}#mermaid-svg-WoyAl3NPEGyJdv2w .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-WoyAl3NPEGyJdv2w .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-WoyAl3NPEGyJdv2w .task.clickable{cursor:pointer}#mermaid-svg-WoyAl3NPEGyJdv2w .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-WoyAl3NPEGyJdv2w .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-WoyAl3NPEGyJdv2w .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-WoyAl3NPEGyJdv2w .taskText0,#mermaid-svg-WoyAl3NPEGyJdv2w .taskText1,#mermaid-svg-WoyAl3NPEGyJdv2w .taskText2,#mermaid-svg-WoyAl3NPEGyJdv2w .taskText3{fill:#fff}#mermaid-svg-WoyAl3NPEGyJdv2w .task0,#mermaid-svg-WoyAl3NPEGyJdv2w .task1,#mermaid-svg-WoyAl3NPEGyJdv2w .task2,#mermaid-svg-WoyAl3NPEGyJdv2w .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-WoyAl3NPEGyJdv2w .taskTextOutside0,#mermaid-svg-WoyAl3NPEGyJdv2w .taskTextOutside2{fill:#000}#mermaid-svg-WoyAl3NPEGyJdv2w .taskTextOutside1,#mermaid-svg-WoyAl3NPEGyJdv2w .taskTextOutside3{fill:#000}#mermaid-svg-WoyAl3NPEGyJdv2w .active0,#mermaid-svg-WoyAl3NPEGyJdv2w .active1,#mermaid-svg-WoyAl3NPEGyJdv2w .active2,#mermaid-svg-WoyAl3NPEGyJdv2w .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-WoyAl3NPEGyJdv2w .activeText0,#mermaid-svg-WoyAl3NPEGyJdv2w .activeText1,#mermaid-svg-WoyAl3NPEGyJdv2w .activeText2,#mermaid-svg-WoyAl3NPEGyJdv2w .activeText3{fill:#000 !important}#mermaid-svg-WoyAl3NPEGyJdv2w .done0,#mermaid-svg-WoyAl3NPEGyJdv2w .done1,#mermaid-svg-WoyAl3NPEGyJdv2w .done2,#mermaid-svg-WoyAl3NPEGyJdv2w .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-WoyAl3NPEGyJdv2w .doneText0,#mermaid-svg-WoyAl3NPEGyJdv2w .doneText1,#mermaid-svg-WoyAl3NPEGyJdv2w .doneText2,#mermaid-svg-WoyAl3NPEGyJdv2w .doneText3{fill:#000 !important}#mermaid-svg-WoyAl3NPEGyJdv2w .crit0,#mermaid-svg-WoyAl3NPEGyJdv2w .crit1,#mermaid-svg-WoyAl3NPEGyJdv2w .crit2,#mermaid-svg-WoyAl3NPEGyJdv2w .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-WoyAl3NPEGyJdv2w .activeCrit0,#mermaid-svg-WoyAl3NPEGyJdv2w .activeCrit1,#mermaid-svg-WoyAl3NPEGyJdv2w .activeCrit2,#mermaid-svg-WoyAl3NPEGyJdv2w .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-WoyAl3NPEGyJdv2w .doneCrit0,#mermaid-svg-WoyAl3NPEGyJdv2w .doneCrit1,#mermaid-svg-WoyAl3NPEGyJdv2w .doneCrit2,#mermaid-svg-WoyAl3NPEGyJdv2w .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-WoyAl3NPEGyJdv2w .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-WoyAl3NPEGyJdv2w .milestoneText{font-style:italic}#mermaid-svg-WoyAl3NPEGyJdv2w .doneCritText0,#mermaid-svg-WoyAl3NPEGyJdv2w .doneCritText1,#mermaid-svg-WoyAl3NPEGyJdv2w .doneCritText2,#mermaid-svg-WoyAl3NPEGyJdv2w .doneCritText3{fill:#000 !important}#mermaid-svg-WoyAl3NPEGyJdv2w .activeCritText0,#mermaid-svg-WoyAl3NPEGyJdv2w .activeCritText1,#mermaid-svg-WoyAl3NPEGyJdv2w .activeCritText2,#mermaid-svg-WoyAl3NPEGyJdv2w .activeCritText3{fill:#000 !important}#mermaid-svg-WoyAl3NPEGyJdv2w .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-WoyAl3NPEGyJdv2w g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-WoyAl3NPEGyJdv2w g.classGroup text .title{font-weight:bolder}#mermaid-svg-WoyAl3NPEGyJdv2w g.clickable{cursor:pointer}#mermaid-svg-WoyAl3NPEGyJdv2w g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-WoyAl3NPEGyJdv2w g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-WoyAl3NPEGyJdv2w .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-WoyAl3NPEGyJdv2w .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-WoyAl3NPEGyJdv2w .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-WoyAl3NPEGyJdv2w .dashed-line{stroke-dasharray:3}#mermaid-svg-WoyAl3NPEGyJdv2w #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-WoyAl3NPEGyJdv2w #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-WoyAl3NPEGyJdv2w #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-WoyAl3NPEGyJdv2w #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-WoyAl3NPEGyJdv2w #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-WoyAl3NPEGyJdv2w #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-WoyAl3NPEGyJdv2w #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-WoyAl3NPEGyJdv2w #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-WoyAl3NPEGyJdv2w .commit-id,#mermaid-svg-WoyAl3NPEGyJdv2w .commit-msg,#mermaid-svg-WoyAl3NPEGyJdv2w .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-WoyAl3NPEGyJdv2w .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-WoyAl3NPEGyJdv2w .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-WoyAl3NPEGyJdv2w g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-WoyAl3NPEGyJdv2w g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-WoyAl3NPEGyJdv2w g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-WoyAl3NPEGyJdv2w g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-WoyAl3NPEGyJdv2w g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-WoyAl3NPEGyJdv2w g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-WoyAl3NPEGyJdv2w .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-WoyAl3NPEGyJdv2w .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-WoyAl3NPEGyJdv2w .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-WoyAl3NPEGyJdv2w .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-WoyAl3NPEGyJdv2w .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-WoyAl3NPEGyJdv2w .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-WoyAl3NPEGyJdv2w .edgeLabel text{fill:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-WoyAl3NPEGyJdv2w .node circle.state-start{fill:black;stroke:black}#mermaid-svg-WoyAl3NPEGyJdv2w .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-WoyAl3NPEGyJdv2w #statediagram-barbEnd{fill:#9370db}#mermaid-svg-WoyAl3NPEGyJdv2w .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-WoyAl3NPEGyJdv2w .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-WoyAl3NPEGyJdv2w .statediagram-state .divider{stroke:#9370db}#mermaid-svg-WoyAl3NPEGyJdv2w .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-WoyAl3NPEGyJdv2w .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-WoyAl3NPEGyJdv2w .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-WoyAl3NPEGyJdv2w .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-WoyAl3NPEGyJdv2w .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-WoyAl3NPEGyJdv2w .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-WoyAl3NPEGyJdv2w .note-edge{stroke-dasharray:5}#mermaid-svg-WoyAl3NPEGyJdv2w .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-WoyAl3NPEGyJdv2w .error-icon{fill:#522}#mermaid-svg-WoyAl3NPEGyJdv2w .error-text{fill:#522;stroke:#522}#mermaid-svg-WoyAl3NPEGyJdv2w .edge-thickness-normal{stroke-width:2px}#mermaid-svg-WoyAl3NPEGyJdv2w .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-WoyAl3NPEGyJdv2w .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-WoyAl3NPEGyJdv2w .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-WoyAl3NPEGyJdv2w .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-WoyAl3NPEGyJdv2w .marker{fill:#333}#mermaid-svg-WoyAl3NPEGyJdv2w .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-WoyAl3NPEGyJdv2w {color: rgba(0, 0, 0, 0.75);font: ;}

cv::warpAffine
hal::warpAffine

检查输入通道数量以及插值类型。
如果目的矩阵为空则创建内存,如果是原地操作则复制一份源数据。

    CV_INSTRUMENT_REGION();int interpolation = flags & INTER_MAX;CV_Assert( _src.channels() <= 4 || (interpolation != INTER_LANCZOS4 &&interpolation != INTER_CUBIC) );CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat() &&_src.cols() <= SHRT_MAX && _src.rows() <= SHRT_MAX,ocl_warpTransform_cols4(_src, _dst, _M0, dsize, flags, borderType,borderValue, OCL_OP_AFFINE))CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),ocl_warpTransform(_src, _dst, _M0, dsize, flags, borderType,borderValue, OCL_OP_AFFINE))Mat src = _src.getMat(), M0 = _M0.getMat();_dst.create( dsize.empty() ? src.size() : dsize, src.type() );Mat dst = _dst.getMat();CV_Assert( src.cols > 0 && src.rows > 0 );if( dst.data == src.data )src = src.clone();

如果未设置WARP_INVERSE_MAP,则对参数矩阵M求逆。

    double M[6] = {0};Mat matM(2, 3, CV_64F, M);if( interpolation == INTER_AREA )interpolation = INTER_LINEAR;CV_Assert( (M0.type() == CV_32F || M0.type() == CV_64F) && M0.rows == 2 && M0.cols == 3 );M0.convertTo(matM, matM.type());if( !(flags & WARP_INVERSE_MAP) ){double D = M[0]*M[4] - M[1]*M[3];D = D != 0 ? 1./D : 0;double A11 = M[4]*D, A22=M[0]*D;M[0] = A11; M[1] *= -D;M[3] *= -D; M[4] = A22;double b1 = -M[0]*M[2] - M[1]*M[5];double b2 = -M[3]*M[2] - M[4]*M[5];M[2] = b1; M[5] = b2;}
#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && !IPP_DISABLE_WARPAFFINECV_IPP_CHECK(){int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);if( ( depth == CV_8U || depth == CV_16U || depth == CV_32F ) &&( cn == 1 || cn == 3 || cn == 4 ) &&( interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC) &&( borderType == cv::BORDER_TRANSPARENT || borderType == cv::BORDER_CONSTANT) ){ippiWarpAffineBackFunc ippFunc = 0;if ((flags & WARP_INVERSE_MAP) != 0){ippFunc =type == CV_8UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C1R :type == CV_8UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C3R :type == CV_8UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C4R :type == CV_16UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C1R :type == CV_16UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C3R :type == CV_16UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C4R :type == CV_32FC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C1R :type == CV_32FC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C3R :type == CV_32FC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C4R :0;}else{ippFunc =type == CV_8UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffine_8u_C1R :type == CV_8UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffine_8u_C3R :type == CV_8UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffine_8u_C4R :type == CV_16UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffine_16u_C1R :type == CV_16UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffine_16u_C3R :type == CV_16UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffine_16u_C4R :type == CV_32FC1 ? (ippiWarpAffineBackFunc)ippiWarpAffine_32f_C1R :type == CV_32FC3 ? (ippiWarpAffineBackFunc)ippiWarpAffine_32f_C3R :type == CV_32FC4 ? (ippiWarpAffineBackFunc)ippiWarpAffine_32f_C4R :0;}int mode =interpolation == INTER_LINEAR ? IPPI_INTER_LINEAR :interpolation == INTER_NEAREST ? IPPI_INTER_NN :interpolation == INTER_CUBIC ? IPPI_INTER_CUBIC :0;CV_Assert(mode && ippFunc);double coeffs[2][3];for( int i = 0; i < 2; i++ )for( int j = 0; j < 3; j++ )coeffs[i][j] = matM.at<double>(i, j);bool ok;Range range(0, dst.rows);IPPWarpAffineInvoker invoker(src, dst, coeffs, mode, borderType, borderValue, ippFunc, &ok);parallel_for_(range, invoker, dst.total()/(double)(1<<16));if( ok ){CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT);return;}setIppErrorStatus();}}
#endif

调用命名空间中的 hal::warpAffine 函数,各参数独立传入。

    hal::warpAffine(src.type(), src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows,M, interpolation, borderType, borderValue.val);

hal::warpAffine

#mermaid-svg-sPkHUqRxxuXXuY84 .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .label text{fill:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .node rect,#mermaid-svg-sPkHUqRxxuXXuY84 .node circle,#mermaid-svg-sPkHUqRxxuXXuY84 .node ellipse,#mermaid-svg-sPkHUqRxxuXXuY84 .node polygon,#mermaid-svg-sPkHUqRxxuXXuY84 .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-sPkHUqRxxuXXuY84 .node .label{text-align:center;fill:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .node.clickable{cursor:pointer}#mermaid-svg-sPkHUqRxxuXXuY84 .arrowheadPath{fill:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-sPkHUqRxxuXXuY84 .flowchart-link{stroke:#333;fill:none}#mermaid-svg-sPkHUqRxxuXXuY84 .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-sPkHUqRxxuXXuY84 .edgeLabel rect{opacity:0.9}#mermaid-svg-sPkHUqRxxuXXuY84 .edgeLabel span{color:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-sPkHUqRxxuXXuY84 .cluster text{fill:#333}#mermaid-svg-sPkHUqRxxuXXuY84 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-sPkHUqRxxuXXuY84 .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-sPkHUqRxxuXXuY84 text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-sPkHUqRxxuXXuY84 .actor-line{stroke:grey}#mermaid-svg-sPkHUqRxxuXXuY84 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-sPkHUqRxxuXXuY84 #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .sequenceNumber{fill:#fff}#mermaid-svg-sPkHUqRxxuXXuY84 #sequencenumber{fill:#333}#mermaid-svg-sPkHUqRxxuXXuY84 #crosshead path{fill:#333;stroke:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .messageText{fill:#333;stroke:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-sPkHUqRxxuXXuY84 .labelText,#mermaid-svg-sPkHUqRxxuXXuY84 .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-sPkHUqRxxuXXuY84 .loopText,#mermaid-svg-sPkHUqRxxuXXuY84 .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-sPkHUqRxxuXXuY84 .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-sPkHUqRxxuXXuY84 .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-sPkHUqRxxuXXuY84 .noteText,#mermaid-svg-sPkHUqRxxuXXuY84 .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-sPkHUqRxxuXXuY84 .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-sPkHUqRxxuXXuY84 .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-sPkHUqRxxuXXuY84 .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-sPkHUqRxxuXXuY84 .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-sPkHUqRxxuXXuY84 .section{stroke:none;opacity:0.2}#mermaid-svg-sPkHUqRxxuXXuY84 .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-sPkHUqRxxuXXuY84 .section2{fill:#fff400}#mermaid-svg-sPkHUqRxxuXXuY84 .section1,#mermaid-svg-sPkHUqRxxuXXuY84 .section3{fill:#fff;opacity:0.2}#mermaid-svg-sPkHUqRxxuXXuY84 .sectionTitle0{fill:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .sectionTitle1{fill:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .sectionTitle2{fill:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .sectionTitle3{fill:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-sPkHUqRxxuXXuY84 .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-sPkHUqRxxuXXuY84 .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-sPkHUqRxxuXXuY84 .grid path{stroke-width:0}#mermaid-svg-sPkHUqRxxuXXuY84 .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-sPkHUqRxxuXXuY84 .task{stroke-width:2}#mermaid-svg-sPkHUqRxxuXXuY84 .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-sPkHUqRxxuXXuY84 .taskText:not([font-size]){font-size:11px}#mermaid-svg-sPkHUqRxxuXXuY84 .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-sPkHUqRxxuXXuY84 .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-sPkHUqRxxuXXuY84 .task.clickable{cursor:pointer}#mermaid-svg-sPkHUqRxxuXXuY84 .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-sPkHUqRxxuXXuY84 .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-sPkHUqRxxuXXuY84 .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-sPkHUqRxxuXXuY84 .taskText0,#mermaid-svg-sPkHUqRxxuXXuY84 .taskText1,#mermaid-svg-sPkHUqRxxuXXuY84 .taskText2,#mermaid-svg-sPkHUqRxxuXXuY84 .taskText3{fill:#fff}#mermaid-svg-sPkHUqRxxuXXuY84 .task0,#mermaid-svg-sPkHUqRxxuXXuY84 .task1,#mermaid-svg-sPkHUqRxxuXXuY84 .task2,#mermaid-svg-sPkHUqRxxuXXuY84 .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-sPkHUqRxxuXXuY84 .taskTextOutside0,#mermaid-svg-sPkHUqRxxuXXuY84 .taskTextOutside2{fill:#000}#mermaid-svg-sPkHUqRxxuXXuY84 .taskTextOutside1,#mermaid-svg-sPkHUqRxxuXXuY84 .taskTextOutside3{fill:#000}#mermaid-svg-sPkHUqRxxuXXuY84 .active0,#mermaid-svg-sPkHUqRxxuXXuY84 .active1,#mermaid-svg-sPkHUqRxxuXXuY84 .active2,#mermaid-svg-sPkHUqRxxuXXuY84 .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-sPkHUqRxxuXXuY84 .activeText0,#mermaid-svg-sPkHUqRxxuXXuY84 .activeText1,#mermaid-svg-sPkHUqRxxuXXuY84 .activeText2,#mermaid-svg-sPkHUqRxxuXXuY84 .activeText3{fill:#000 !important}#mermaid-svg-sPkHUqRxxuXXuY84 .done0,#mermaid-svg-sPkHUqRxxuXXuY84 .done1,#mermaid-svg-sPkHUqRxxuXXuY84 .done2,#mermaid-svg-sPkHUqRxxuXXuY84 .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-sPkHUqRxxuXXuY84 .doneText0,#mermaid-svg-sPkHUqRxxuXXuY84 .doneText1,#mermaid-svg-sPkHUqRxxuXXuY84 .doneText2,#mermaid-svg-sPkHUqRxxuXXuY84 .doneText3{fill:#000 !important}#mermaid-svg-sPkHUqRxxuXXuY84 .crit0,#mermaid-svg-sPkHUqRxxuXXuY84 .crit1,#mermaid-svg-sPkHUqRxxuXXuY84 .crit2,#mermaid-svg-sPkHUqRxxuXXuY84 .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-sPkHUqRxxuXXuY84 .activeCrit0,#mermaid-svg-sPkHUqRxxuXXuY84 .activeCrit1,#mermaid-svg-sPkHUqRxxuXXuY84 .activeCrit2,#mermaid-svg-sPkHUqRxxuXXuY84 .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-sPkHUqRxxuXXuY84 .doneCrit0,#mermaid-svg-sPkHUqRxxuXXuY84 .doneCrit1,#mermaid-svg-sPkHUqRxxuXXuY84 .doneCrit2,#mermaid-svg-sPkHUqRxxuXXuY84 .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-sPkHUqRxxuXXuY84 .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-sPkHUqRxxuXXuY84 .milestoneText{font-style:italic}#mermaid-svg-sPkHUqRxxuXXuY84 .doneCritText0,#mermaid-svg-sPkHUqRxxuXXuY84 .doneCritText1,#mermaid-svg-sPkHUqRxxuXXuY84 .doneCritText2,#mermaid-svg-sPkHUqRxxuXXuY84 .doneCritText3{fill:#000 !important}#mermaid-svg-sPkHUqRxxuXXuY84 .activeCritText0,#mermaid-svg-sPkHUqRxxuXXuY84 .activeCritText1,#mermaid-svg-sPkHUqRxxuXXuY84 .activeCritText2,#mermaid-svg-sPkHUqRxxuXXuY84 .activeCritText3{fill:#000 !important}#mermaid-svg-sPkHUqRxxuXXuY84 .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-sPkHUqRxxuXXuY84 g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-sPkHUqRxxuXXuY84 g.classGroup text .title{font-weight:bolder}#mermaid-svg-sPkHUqRxxuXXuY84 g.clickable{cursor:pointer}#mermaid-svg-sPkHUqRxxuXXuY84 g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-sPkHUqRxxuXXuY84 g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-sPkHUqRxxuXXuY84 .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-sPkHUqRxxuXXuY84 .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-sPkHUqRxxuXXuY84 .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-sPkHUqRxxuXXuY84 .dashed-line{stroke-dasharray:3}#mermaid-svg-sPkHUqRxxuXXuY84 #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-sPkHUqRxxuXXuY84 #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-sPkHUqRxxuXXuY84 #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-sPkHUqRxxuXXuY84 #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-sPkHUqRxxuXXuY84 #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-sPkHUqRxxuXXuY84 #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-sPkHUqRxxuXXuY84 #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-sPkHUqRxxuXXuY84 #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-sPkHUqRxxuXXuY84 .commit-id,#mermaid-svg-sPkHUqRxxuXXuY84 .commit-msg,#mermaid-svg-sPkHUqRxxuXXuY84 .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-sPkHUqRxxuXXuY84 .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-sPkHUqRxxuXXuY84 .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-sPkHUqRxxuXXuY84 g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-sPkHUqRxxuXXuY84 g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-sPkHUqRxxuXXuY84 g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-sPkHUqRxxuXXuY84 g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-sPkHUqRxxuXXuY84 g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-sPkHUqRxxuXXuY84 g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-sPkHUqRxxuXXuY84 .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-sPkHUqRxxuXXuY84 .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-sPkHUqRxxuXXuY84 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-sPkHUqRxxuXXuY84 .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-sPkHUqRxxuXXuY84 .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-sPkHUqRxxuXXuY84 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-sPkHUqRxxuXXuY84 .edgeLabel text{fill:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-sPkHUqRxxuXXuY84 .node circle.state-start{fill:black;stroke:black}#mermaid-svg-sPkHUqRxxuXXuY84 .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-sPkHUqRxxuXXuY84 #statediagram-barbEnd{fill:#9370db}#mermaid-svg-sPkHUqRxxuXXuY84 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-sPkHUqRxxuXXuY84 .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-sPkHUqRxxuXXuY84 .statediagram-state .divider{stroke:#9370db}#mermaid-svg-sPkHUqRxxuXXuY84 .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-sPkHUqRxxuXXuY84 .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-sPkHUqRxxuXXuY84 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-sPkHUqRxxuXXuY84 .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-sPkHUqRxxuXXuY84 .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-sPkHUqRxxuXXuY84 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-sPkHUqRxxuXXuY84 .note-edge{stroke-dasharray:5}#mermaid-svg-sPkHUqRxxuXXuY84 .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-sPkHUqRxxuXXuY84 .error-icon{fill:#522}#mermaid-svg-sPkHUqRxxuXXuY84 .error-text{fill:#522;stroke:#522}#mermaid-svg-sPkHUqRxxuXXuY84 .edge-thickness-normal{stroke-width:2px}#mermaid-svg-sPkHUqRxxuXXuY84 .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-sPkHUqRxxuXXuY84 .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-sPkHUqRxxuXXuY84 .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-sPkHUqRxxuXXuY84 .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-sPkHUqRxxuXXuY84 .marker{fill:#333}#mermaid-svg-sPkHUqRxxuXXuY84 .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-sPkHUqRxxuXXuY84 {color: rgba(0, 0, 0, 0.75);font: ;}

hal::warpAffine
parallel_for_
WarpAffineInvoker

dst(x,y)=src(M11x+M12y+M13,M21x+M22y+M23)\mathrm{dst}(x,y)=\mathrm{src}(M_{11}x+M_{12}y+M_{13}, M_{21}x+M_{22}y+M_{23})dst(x,y)=src(M11​x+M12​y+M13​,M21​x+M22​y+M23​)

OpenCV 屏蔽了 Carotene 中的实现。
根据描述构建出源和目的矩阵。
INTER_BITS 为5,即插值所用比特数。
预先计算行元素变换系数,adelta为 M11xM_{11}xM11​x,bdelta为 M21xM_{21}xM21​x。

    CALL_HAL(warpAffine, cv_hal_warpAffine, src_type, src_data, src_step, src_width, src_height, dst_data, dst_step, dst_width, dst_height, M, interpolation, borderType, borderValue);Mat src(Size(src_width, src_height), src_type, const_cast<uchar*>(src_data), src_step);Mat dst(Size(dst_width, dst_height), src_type, dst_data, dst_step);int x;AutoBuffer<int> _abdelta(dst.cols*2);int* adelta = &_abdelta[0], *bdelta = adelta + dst.cols;const int AB_BITS = MAX(10, (int)INTER_BITS);const int AB_SCALE = 1 << AB_BITS;for( x = 0; x < dst.cols; x++ ){adelta[x] = saturate_cast<int>(M[0]*x*AB_SCALE);bdelta[x] = saturate_cast<int>(M[3]*x*AB_SCALE);}

创建调用者 WarpAffineInvoker,parallel_for_ 函数并行调用。

    Range range(0, dst.rows);WarpAffineInvoker invoker(src, dst, interpolation, borderType,Scalar(borderValue[0], borderValue[1], borderValue[2], borderValue[3]),adelta, bdelta, M);parallel_for_(range, invoker, dst.total()/(double)(1<<16));

WarpAffineInvoker

#mermaid-svg-qGc42t0oMFWIR4US .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-qGc42t0oMFWIR4US .label text{fill:#333}#mermaid-svg-qGc42t0oMFWIR4US .node rect,#mermaid-svg-qGc42t0oMFWIR4US .node circle,#mermaid-svg-qGc42t0oMFWIR4US .node ellipse,#mermaid-svg-qGc42t0oMFWIR4US .node polygon,#mermaid-svg-qGc42t0oMFWIR4US .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-qGc42t0oMFWIR4US .node .label{text-align:center;fill:#333}#mermaid-svg-qGc42t0oMFWIR4US .node.clickable{cursor:pointer}#mermaid-svg-qGc42t0oMFWIR4US .arrowheadPath{fill:#333}#mermaid-svg-qGc42t0oMFWIR4US .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-qGc42t0oMFWIR4US .flowchart-link{stroke:#333;fill:none}#mermaid-svg-qGc42t0oMFWIR4US .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-qGc42t0oMFWIR4US .edgeLabel rect{opacity:0.9}#mermaid-svg-qGc42t0oMFWIR4US .edgeLabel span{color:#333}#mermaid-svg-qGc42t0oMFWIR4US .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-qGc42t0oMFWIR4US .cluster text{fill:#333}#mermaid-svg-qGc42t0oMFWIR4US div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-qGc42t0oMFWIR4US .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-qGc42t0oMFWIR4US text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-qGc42t0oMFWIR4US .actor-line{stroke:grey}#mermaid-svg-qGc42t0oMFWIR4US .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-qGc42t0oMFWIR4US .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-qGc42t0oMFWIR4US #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-qGc42t0oMFWIR4US .sequenceNumber{fill:#fff}#mermaid-svg-qGc42t0oMFWIR4US #sequencenumber{fill:#333}#mermaid-svg-qGc42t0oMFWIR4US #crosshead path{fill:#333;stroke:#333}#mermaid-svg-qGc42t0oMFWIR4US .messageText{fill:#333;stroke:#333}#mermaid-svg-qGc42t0oMFWIR4US .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-qGc42t0oMFWIR4US .labelText,#mermaid-svg-qGc42t0oMFWIR4US .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-qGc42t0oMFWIR4US .loopText,#mermaid-svg-qGc42t0oMFWIR4US .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-qGc42t0oMFWIR4US .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-qGc42t0oMFWIR4US .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-qGc42t0oMFWIR4US .noteText,#mermaid-svg-qGc42t0oMFWIR4US .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-qGc42t0oMFWIR4US .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-qGc42t0oMFWIR4US .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-qGc42t0oMFWIR4US .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-qGc42t0oMFWIR4US .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-qGc42t0oMFWIR4US .section{stroke:none;opacity:0.2}#mermaid-svg-qGc42t0oMFWIR4US .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-qGc42t0oMFWIR4US .section2{fill:#fff400}#mermaid-svg-qGc42t0oMFWIR4US .section1,#mermaid-svg-qGc42t0oMFWIR4US .section3{fill:#fff;opacity:0.2}#mermaid-svg-qGc42t0oMFWIR4US .sectionTitle0{fill:#333}#mermaid-svg-qGc42t0oMFWIR4US .sectionTitle1{fill:#333}#mermaid-svg-qGc42t0oMFWIR4US .sectionTitle2{fill:#333}#mermaid-svg-qGc42t0oMFWIR4US .sectionTitle3{fill:#333}#mermaid-svg-qGc42t0oMFWIR4US .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-qGc42t0oMFWIR4US .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-qGc42t0oMFWIR4US .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-qGc42t0oMFWIR4US .grid path{stroke-width:0}#mermaid-svg-qGc42t0oMFWIR4US .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-qGc42t0oMFWIR4US .task{stroke-width:2}#mermaid-svg-qGc42t0oMFWIR4US .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-qGc42t0oMFWIR4US .taskText:not([font-size]){font-size:11px}#mermaid-svg-qGc42t0oMFWIR4US .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-qGc42t0oMFWIR4US .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-qGc42t0oMFWIR4US .task.clickable{cursor:pointer}#mermaid-svg-qGc42t0oMFWIR4US .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-qGc42t0oMFWIR4US .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-qGc42t0oMFWIR4US .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-qGc42t0oMFWIR4US .taskText0,#mermaid-svg-qGc42t0oMFWIR4US .taskText1,#mermaid-svg-qGc42t0oMFWIR4US .taskText2,#mermaid-svg-qGc42t0oMFWIR4US .taskText3{fill:#fff}#mermaid-svg-qGc42t0oMFWIR4US .task0,#mermaid-svg-qGc42t0oMFWIR4US .task1,#mermaid-svg-qGc42t0oMFWIR4US .task2,#mermaid-svg-qGc42t0oMFWIR4US .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-qGc42t0oMFWIR4US .taskTextOutside0,#mermaid-svg-qGc42t0oMFWIR4US .taskTextOutside2{fill:#000}#mermaid-svg-qGc42t0oMFWIR4US .taskTextOutside1,#mermaid-svg-qGc42t0oMFWIR4US .taskTextOutside3{fill:#000}#mermaid-svg-qGc42t0oMFWIR4US .active0,#mermaid-svg-qGc42t0oMFWIR4US .active1,#mermaid-svg-qGc42t0oMFWIR4US .active2,#mermaid-svg-qGc42t0oMFWIR4US .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-qGc42t0oMFWIR4US .activeText0,#mermaid-svg-qGc42t0oMFWIR4US .activeText1,#mermaid-svg-qGc42t0oMFWIR4US .activeText2,#mermaid-svg-qGc42t0oMFWIR4US .activeText3{fill:#000 !important}#mermaid-svg-qGc42t0oMFWIR4US .done0,#mermaid-svg-qGc42t0oMFWIR4US .done1,#mermaid-svg-qGc42t0oMFWIR4US .done2,#mermaid-svg-qGc42t0oMFWIR4US .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-qGc42t0oMFWIR4US .doneText0,#mermaid-svg-qGc42t0oMFWIR4US .doneText1,#mermaid-svg-qGc42t0oMFWIR4US .doneText2,#mermaid-svg-qGc42t0oMFWIR4US .doneText3{fill:#000 !important}#mermaid-svg-qGc42t0oMFWIR4US .crit0,#mermaid-svg-qGc42t0oMFWIR4US .crit1,#mermaid-svg-qGc42t0oMFWIR4US .crit2,#mermaid-svg-qGc42t0oMFWIR4US .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-qGc42t0oMFWIR4US .activeCrit0,#mermaid-svg-qGc42t0oMFWIR4US .activeCrit1,#mermaid-svg-qGc42t0oMFWIR4US .activeCrit2,#mermaid-svg-qGc42t0oMFWIR4US .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-qGc42t0oMFWIR4US .doneCrit0,#mermaid-svg-qGc42t0oMFWIR4US .doneCrit1,#mermaid-svg-qGc42t0oMFWIR4US .doneCrit2,#mermaid-svg-qGc42t0oMFWIR4US .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-qGc42t0oMFWIR4US .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-qGc42t0oMFWIR4US .milestoneText{font-style:italic}#mermaid-svg-qGc42t0oMFWIR4US .doneCritText0,#mermaid-svg-qGc42t0oMFWIR4US .doneCritText1,#mermaid-svg-qGc42t0oMFWIR4US .doneCritText2,#mermaid-svg-qGc42t0oMFWIR4US .doneCritText3{fill:#000 !important}#mermaid-svg-qGc42t0oMFWIR4US .activeCritText0,#mermaid-svg-qGc42t0oMFWIR4US .activeCritText1,#mermaid-svg-qGc42t0oMFWIR4US .activeCritText2,#mermaid-svg-qGc42t0oMFWIR4US .activeCritText3{fill:#000 !important}#mermaid-svg-qGc42t0oMFWIR4US .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-qGc42t0oMFWIR4US g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-qGc42t0oMFWIR4US g.classGroup text .title{font-weight:bolder}#mermaid-svg-qGc42t0oMFWIR4US g.clickable{cursor:pointer}#mermaid-svg-qGc42t0oMFWIR4US g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-qGc42t0oMFWIR4US g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-qGc42t0oMFWIR4US .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-qGc42t0oMFWIR4US .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-qGc42t0oMFWIR4US .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-qGc42t0oMFWIR4US .dashed-line{stroke-dasharray:3}#mermaid-svg-qGc42t0oMFWIR4US #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-qGc42t0oMFWIR4US #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-qGc42t0oMFWIR4US #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-qGc42t0oMFWIR4US #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-qGc42t0oMFWIR4US #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-qGc42t0oMFWIR4US #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-qGc42t0oMFWIR4US #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-qGc42t0oMFWIR4US #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-qGc42t0oMFWIR4US .commit-id,#mermaid-svg-qGc42t0oMFWIR4US .commit-msg,#mermaid-svg-qGc42t0oMFWIR4US .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-qGc42t0oMFWIR4US .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-qGc42t0oMFWIR4US .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-qGc42t0oMFWIR4US g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-qGc42t0oMFWIR4US g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-qGc42t0oMFWIR4US g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-qGc42t0oMFWIR4US g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-qGc42t0oMFWIR4US g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-qGc42t0oMFWIR4US g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-qGc42t0oMFWIR4US .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-qGc42t0oMFWIR4US .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-qGc42t0oMFWIR4US .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-qGc42t0oMFWIR4US .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-qGc42t0oMFWIR4US .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-qGc42t0oMFWIR4US .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-qGc42t0oMFWIR4US .edgeLabel text{fill:#333}#mermaid-svg-qGc42t0oMFWIR4US .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-qGc42t0oMFWIR4US .node circle.state-start{fill:black;stroke:black}#mermaid-svg-qGc42t0oMFWIR4US .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-qGc42t0oMFWIR4US #statediagram-barbEnd{fill:#9370db}#mermaid-svg-qGc42t0oMFWIR4US .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-qGc42t0oMFWIR4US .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-qGc42t0oMFWIR4US .statediagram-state .divider{stroke:#9370db}#mermaid-svg-qGc42t0oMFWIR4US .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-qGc42t0oMFWIR4US .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-qGc42t0oMFWIR4US .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-qGc42t0oMFWIR4US .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-qGc42t0oMFWIR4US .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-qGc42t0oMFWIR4US .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-qGc42t0oMFWIR4US .note-edge{stroke-dasharray:5}#mermaid-svg-qGc42t0oMFWIR4US .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-qGc42t0oMFWIR4US .error-icon{fill:#522}#mermaid-svg-qGc42t0oMFWIR4US .error-text{fill:#522;stroke:#522}#mermaid-svg-qGc42t0oMFWIR4US .edge-thickness-normal{stroke-width:2px}#mermaid-svg-qGc42t0oMFWIR4US .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-qGc42t0oMFWIR4US .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-qGc42t0oMFWIR4US .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-qGc42t0oMFWIR4US .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-qGc42t0oMFWIR4US .marker{fill:#333}#mermaid-svg-qGc42t0oMFWIR4US .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-qGc42t0oMFWIR4US {color: rgba(0, 0, 0, 0.75);font: ;}

WarpAffineInvoker
ParallelLoopBody
public:WarpAffineInvoker(const Mat &_src, Mat &_dst, int _interpolation, int _borderType,const Scalar &_borderValue, int *_adelta, int *_bdelta, const double *_M) :ParallelLoopBody(), src(_src), dst(_dst), interpolation(_interpolation),borderType(_borderType), borderValue(_borderValue), adelta(_adelta), bdelta(_bdelta),M(_M){}

operator()

处理操作符函数。

BLOCK_SZ指定分块大小。
XY存储源图上对应的坐标,A为辅助系数。
INTER_BITS 为5。
INTER_TAB_SIZE 为 2INTER_BITS=322^{\mathrm{INTER\_BITS}}=322INTER_BITS=32,这样双线性插值表大小为32x32x4。
AB_SCALE为 2102^{10}210。这样计算结果的 10.6 的格式存储。
处理区域为BLOCK_SZ/2行、BLOCK_SZ*2列的矩形。为什么?

    virtual void operator() (const Range& range) const CV_OVERRIDE{const int BLOCK_SZ = 64;AutoBuffer<short, 0> __XY(BLOCK_SZ * BLOCK_SZ * 2), __A(BLOCK_SZ * BLOCK_SZ);short *XY = __XY.data(), *A = __A.data();const int AB_BITS = MAX(10, (int)INTER_BITS);const int AB_SCALE = 1 << AB_BITS;int round_delta = interpolation == INTER_NEAREST ? AB_SCALE/2 : AB_SCALE/INTER_TAB_SIZE/2, x, y, x1, y1;#if CV_TRY_AVX2bool useAVX2 = CV_CPU_HAS_SUPPORT_AVX2;#endif#if CV_TRY_SSE4_1bool useSSE4_1 = CV_CPU_HAS_SUPPORT_SSE4_1;#endifint bh0 = std::min(BLOCK_SZ/2, dst.rows);int bw0 = std::min(BLOCK_SZ*BLOCK_SZ/bh0, dst.cols);bh0 = std::min(BLOCK_SZ*BLOCK_SZ/bw0, dst.rows);

xy指向结果矩阵的当前行行首。
X0为 M12y+M13M_{12}y+M_{13}M12​y+M13​
Y0为 M22x+M23M_{22}x+M_{23}M22​x+M23​
round_delta为16。
_XY将缓冲区__XY封装成了矩阵。
dpart为结果的 RoI 区域。

        for( y = range.start; y < range.end; y += bh0 ){for( x = 0; x < dst.cols; x += bw0 ){int bw = std::min( bw0, dst.cols - x);int bh = std::min( bh0, range.end - y);Mat _XY(bh, bw, CV_16SC2, XY), matA;Mat dpart(dst, Rect(x, y, bw, bh));for( y1 = 0; y1 < bh; y1++ ){short* xy = XY + y1*bw*2;int X0 = saturate_cast<int>((M[1]*(y + y1) + M[2])*AB_SCALE) + round_delta;int Y0 = saturate_cast<int>((M[4]*(y + y1) + M[5])*AB_SCALE) + round_delta;

如果是最近邻方法。
WarpAffineInvoker_Blockline_SSE41

                    if( interpolation == INTER_NEAREST ){x1 = 0;#if CV_TRY_SSE4_1if( useSSE4_1 )opt_SSE4_1::WarpAffineInvoker_Blockline_SSE41(adelta + x, bdelta + x, xy, X0, Y0, bw);else#endif{#if CV_SIMD128{v_int32x4 v_X0 = v_setall_s32(X0), v_Y0 = v_setall_s32(Y0);int span = v_uint16x8::nlanes;for( ; x1 <= bw - span; x1 += span ){v_int16x8 v_dst[2];#define CV_CONVERT_MAP(ptr,offset,shift) v_pack(v_shr<AB_BITS>(shift+v_load(ptr + offset)),\v_shr<AB_BITS>(shift+v_load(ptr + offset + 4)))v_dst[0] = CV_CONVERT_MAP(adelta, x+x1, v_X0);v_dst[1] = CV_CONVERT_MAP(bdelta, x+x1, v_Y0);#undef CV_CONVERT_MAPv_store_interleave(xy + (x1 << 1), v_dst[0], v_dst[1]);}}#endiffor( ; x1 < bw; x1++ ){int X = (X0 + adelta[x+x1]) >> AB_BITS;int Y = (Y0 + bdelta[x+x1]) >> AB_BITS;xy[x1*2] = saturate_cast<short>(X);xy[x1*2+1] = saturate_cast<short>(Y);}}}

对于双线性插值。
alpha指向当前行。
avx2可以调用 warpAffineBlockline
v_mask为向量掩码。
每次处理span*2个数。
v_setall_s32 通过 OPENCV_HAL_IMPL_NEON_INIT 宏来定义。
v_load 从存储器中加载寄存器内容。
计算 M11x+M12y+M13M_{11}x+M_{12}y+M_{13}M11​x+M12​y+M13​ 和 M21x+M22y+M23M_{21}x+M_{22}y+M_{23}M21​x+M22​y+M23​ 时,是两个v_int32x4相加(vaddq_s32),得到v_int32x4的结果。然后右移 (10-5)位。
v_shr 右移。
v_pack 将两个数据宽度减半后拼到一起。
两次右移后
v_store_interleave 将2个寄存器中的数据交错存储到内存中。
v_shl 左移。
v_store 将寄存器内容存储到内存中。
v_Y0v_X0合并。

                    else{short* alpha = A + y1*bw;x1 = 0;#if CV_TRY_AVX2if ( useAVX2 )x1 = opt_AVX2::warpAffineBlockline(adelta + x, bdelta + x, xy, alpha, X0, Y0, bw);#endif#if CV_SIMD128{v_int32x4 v__X0 = v_setall_s32(X0), v__Y0 = v_setall_s32(Y0);v_int32x4 v_mask = v_setall_s32(INTER_TAB_SIZE - 1);int span = v_float32x4::nlanes;for( ; x1 <= bw - span * 2; x1 += span * 2 ){v_int32x4 v_X0 = v_shr<AB_BITS - INTER_BITS>(v__X0 + v_load(adelta + x + x1));v_int32x4 v_Y0 = v_shr<AB_BITS - INTER_BITS>(v__Y0 + v_load(bdelta + x + x1));v_int32x4 v_X1 = v_shr<AB_BITS - INTER_BITS>(v__X0 + v_load(adelta + x + x1 + span));v_int32x4 v_Y1 = v_shr<AB_BITS - INTER_BITS>(v__Y0 + v_load(bdelta + x + x1 + span));v_int16x8 v_xy[2];v_xy[0] = v_pack(v_shr<INTER_BITS>(v_X0), v_shr<INTER_BITS>(v_X1));v_xy[1] = v_pack(v_shr<INTER_BITS>(v_Y0), v_shr<INTER_BITS>(v_Y1));v_store_interleave(xy + (x1 << 1), v_xy[0], v_xy[1]);v_int32x4 v_alpha0 = v_shl<INTER_BITS>(v_Y0 & v_mask) | (v_X0 & v_mask);v_int32x4 v_alpha1 = v_shl<INTER_BITS>(v_Y1 & v_mask) | (v_X1 & v_mask);v_store(alpha + x1, v_pack(v_alpha0, v_alpha1));}}#endif

XY为映射到源图上的像素坐标。alphaYX的小数部分合并存储。

                        for( ; x1 < bw; x1++ ){int X = (X0 + adelta[x+x1]) >> (AB_BITS - INTER_BITS);int Y = (Y0 + bdelta[x+x1]) >> (AB_BITS - INTER_BITS);xy[x1*2] = saturate_cast<short>(X >> INTER_BITS);xy[x1*2+1] = saturate_cast<short>(Y >> INTER_BITS);alpha[x1] = (short)((Y & (INTER_TAB_SIZE-1))*INTER_TAB_SIZE +(X & (INTER_TAB_SIZE-1)));}}}

cv::remap 从src中找到dpart的源值。最近邻方式不需要第二张图。

                if( interpolation == INTER_NEAREST )remap( src, dpart, _XY, Mat(), interpolation, borderType, borderValue );else{Mat _matA(bh, bw, CV_16U, A);remap( src, dpart, _XY, _matA, interpolation, borderType, borderValue );}}}}

成员变量。

private:Mat src;Mat dst;int interpolation, borderType;Scalar borderValue;int *adelta, *bdelta;const double *M;

参考资料:

  • Warp Affine
  • How to work with OpenCV application based on OpenVX API
  • OpenVX sample #7163
  • opencv/cmake/FindOpenVX.cmake
  • Hybrid CV/DL pipelines with OpenCV 4.4 G-API
  • opencv和openvx
  • Showing our vision with OpenVX™ 1.1 support for PowerVR GPUs
  • Amdovx Core
  • OpenVX 1.3 is Here!
  • Color Copy OpenVX* Sample
  • opencv ncnn warpaffine 性能测试
  • OpenCV warpAffine的天坑
  • Geometric Transformations of Images
  • Decompose a 2D arbitrary transform into only scaling and rotation
  • Decompose affine transformation (including shear in x and y)
  • Decomposing an Affine transformation
  • Decomposing an Affine transformation
  • Given this transformation matrix, how do I decompose it into translation, rotation and scale matrices?
  • Opencv 仿射变换原理代码解析
  • 如何通俗地讲解「仿射变换」这个概念?
  • OpenCV代码提取:warpAffine函数的实现
  • NEON优化——OpenCV WarpAffine最近邻
  • Subtracting 0x8000 from an int
  • OpenCV2:Mat属性type,depth,step
  • OpenCV中如何获取Mat类型中的步长stride及分析 C++实现
  • NEON is the new black: fast JPEG optimization on ARM server
  • 大端序与小端序
  • Remapping
  • C++ 命令模式讲解和代码示例
  • Specify an origin to warpPerspective() function in OpenCV 2.x
  • 计算机视觉2D几何基元及其变换介绍和OpenCV WarpPerspective源码分析

OpenCV 中的 warpAffine相关推荐

  1. opencv中cv2.warpAffine 和 cv2.warpPerspective的广泛应用

    大家不要再理解错了!warpPerspective和warpAffine 不仅仅只有透视变换一个作用. 上一次做理论题时,搜索warpPerspective,结果给我弹出来一个透视变换,如下: 当时的 ...

  2. OpenCV中图像旋转(warpAffine)算法的实现过程

    在OpenCV中,目前并没有现成的函数直接用来实现图像旋转,它是用仿射变换函数cv::warpAffine来实现的,此函数目前支持4种插值算法,最近邻.双线性.双三次.兰索斯插值,如果传进去的参数为基 ...

  3. OpenCV中的仿射变换

    OpenCV中的仿射变换 仿射变换:一个任意的仿射变换都能表示为 乘以一个矩阵 (线性变换) 接着再 加上一个向量 (平移). 通常一个图像有三种变换: 1.旋转 2.平移 3.缩放 通常用2X3的矩 ...

  4. OpenCV中的「透视变换 / 投影变换 / 单应性」—cv.warpPerspective、cv.findHomography

    文章目录 引言 透视变换(projective transform) 单应性(Homography) opencv代码 仿射变换相关函数 投影变换相关的函数 鸟瞰图代码示例 小结 引言 图像的几何变换 ...

  5. opencv中mean函数耗时_使用OpenCV进行人脸对齐

    在人脸识别项目中,如果图片中人脸的方向各不一样且相差很大,这样会影响人脸识别的准确率.所以在实际人脸检测项目中,在人脸识别的前一步往往会先进行人脸对齐.人脸对齐可以看作是数据normalization ...

  6. OpenCV中文文档4.0.0学习笔记(更新中……)

    系列文章目录 文章目录 系列文章目录 前言 一.简介 1.OpenCV-Python教程简介 2.OpenCV-Python 3.OpenCV-Python教程 4.OpenCV 需要你!!! 二.G ...

  7. OpenCV中使用Eigenfaces 或 Fisherfaces进行人脸识别

    连接:OpenCV中使用Eigenfaces 或 Fisherfaces进行人脸识别 OpenCV中使用Eigenfaces 或 Fisherfaces进行人脸识别 Translate by Dawn ...

  8. opencv函数cv2.warpAffine 和 cv2.warpPerspective 的理解和复现

    文章目录 opencv函数cv2.warpAffine 和 cv2.warpPerspective 的理解和复现 1. warpAffine 函数处理仿射变换 2. warp_perspective ...

  9. 第四章:OpenCV中的图像处理

    第四章:OpenCV中的图像处理 本章节你将学习图像的改变色彩空间.提取对象.图像的几何变换.图像的阈值.平滑图像等OpenCV图像处理的基本内容. 更多内容请关注我的GitHub库:TonyStar ...

最新文章

  1. MySQL 性能优化及常用命令
  2. Logical Volume Manager(逻辑卷管理)
  3. qt开发游戏必须要了解的数据类
  4. input python_python input 详解
  5. 自定义hybris生成订单的ID格式
  6. mysql 磁盘限额_Linux运维知识之为Linux MySQL数据库设置磁盘限额
  7. java 文件名空格,java关于文件名带有空格的个人见解
  8. PureMVC在Unity游戏开发中的应用
  9. linux下tomcat启动后出现多个java进程
  10. ISO 17799 /27001标准简介
  11. 别让我们的幸福感受在别人眼中
  12. java 微信公众号发红包_微信公众号如何给用户发红包?
  13. Fiddler实现苹果手机APP抓包
  14. 如何用Deep Learning为股票定价
  15. 博途v15模拟量转换_通过实例玩转博途之信号模块参数设置及模拟量输入转换举例...
  16. 【重写】简析stm32启动过程
  17. linux只W25Q256驱动,使用m25p80,支持w25q系列nor flash
  18. matlab 保存色图,如何在matlab中制作“色图”图?
  19. (图解)第十三届蓝桥杯B组省赛 试题 G: 积木画
  20. 局域网无法共享问题的解决

热门文章

  1. 数学学习笔记--线性代数
  2. 阿里云再投2000亿元背后的无奈和坚持
  3. elementary os安装后配置
  4. QQ远程系统权限原因,暂时无法操作
  5. 优信拍集团php面试题_【优信拍PHP工程师面试】优信拍面经。-看准网
  6. 新的一年即将到来,分享2023年火爆的行业和值得做的副业兼职项目
  7. cocos create tween
  8. (三)MAMP的安装及使用
  9. 【电子学会】2021年03月图形化四级 -- 十字回文诗
  10. UCOSIII---共享资源