<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Dissipated Heat</title>
	
	<link>http://dissipatedHeat.com</link>
	<description>Decrease the entropy!</description>
	<lastBuildDate>Mon, 12 Dec 2011 19:46:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/dheat" /><feedburner:info uri="dheat" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>How (not) to write a patch for PostgreSQL</title>
		<link>http://feedproxy.google.com/~r/dheat/~3/lKg1b6KbOTg/</link>
		<comments>http://dissipatedHeat.com/2011/11/10/how-not-to-write-a-patch-for-postgresql/#comments</comments>
		<pubDate>Thu, 10 Nov 2011 17:29:59 +0000</pubDate>
		<dc:creator>Kerem Kat</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[corresponding clause]]></category>
		<category><![CDATA[pgsql-hackers]]></category>
		<category><![CDATA[postgres]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://dissipatedHeat.com/?p=313</guid>
		<description><![CDATA[What In this quick and dirty article, we will be describing a syntax and implementing the new syntax in postgresql backend. The syntax to be implemented is CORRESPONDING clause, which is referenced in the SQL20nn standard draft as &#34;Feature F301, CORRESPONDING in query expressions&#34;. CORRESPONDING clause can be seen as a modifier for set operations <a href='http://dissipatedHeat.com/2011/11/10/how-not-to-write-a-patch-for-postgresql/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<h3>What</h3>
<p>In this quick and dirty article, we will be describing a syntax and implementing the new syntax in <a href="http://www.postgresql.org/" target="_blank">postgresql</a> backend. The syntax to be implemented is CORRESPONDING clause, which is referenced in the SQL20nn standard draft as &quot;Feature F301, CORRESPONDING in query expressions&quot;.</p>
<p>CORRESPONDING clause can be seen as a modifier for set operations in SELECT statements. It filters the projected columns to either match the same column names, or match the column names with a list (CORRESPONDING BY).</p>
<pre>

Note: [] denotes optionality

query1 and query2 are select statements.

&#160;

query1 UNION     [ ALL ] [ CORRESPONDING [ BY ( column_list ) ] ] query2

query1 EXCEPT    [ ALL ] [ CORRESPONDING [ BY ( column_list ) ] ] query2

query1 INTERSECT [ ALL ] [ CORRESPONDING [ BY ( column_list ) ] ] query2
</pre>
<ul>
<li>CORRESPONDING returns all columns that are in both <em>query1</em> and <em>query2</em> with the same name. </li>
<li>CORRESPONDING BY returns all columns in the <em>column_list</em> that are also in both <em>query1</em> and <em>query2</em> with the same name. </li>
</ul>
<p>We will use UNION operator, INTERSECT and EXCEPT works the same with CORRESPONDING clause. Here are some examples to clarify what <strong>CORRESPONDING</strong> means.</p>
<pre>SELECT 1 a, 2 b, 3 c UNION CORRESPONDING SELECT 4 a, 5 b, 6 c;
 a | b | c
---+---+---
 1 | 2 | 3
 4 | 5 | 6
(2 rows)</pre>
<p>Now the fun part, we have removed column <em>b </em>from <em>query2</em>:</p>
<pre>SELECT 1 a, 2 b, 3 c UNION CORRESPONDING SELECT 4 a, 6 c;
 a | c
---+---
 1 | 3
 4 | 6
(2 rows)</pre>
<pre>

SELECT 1 a, 2 b, 3 c UNION CORRESPONDING SELECT 4 d;
ERROR:  UNION queries with a CORRESPONDING clause must have

 at least one column with the same name
</pre>
<p>The idea with CORRESPONDING is, unmatched columns are removed. If no columns left to project, then it is a syntax error.</p>
<p>For the <strong>CORRESPONDING BY</strong>(column_list) part, one more step of filtering is done to ensure that columns in the column_list are present in <em>query1</em> and <em>query2.</em></p>
<pre>SELECT 1 a, 2 b, 3 c UNION CORRESPONDING BY(a, b, c) SELECT 4 a, 5 b, 6 c;
 a | b | c
---+---+---
 1 | 2 | 3
 4 | 5 | 6
(2 rows)</pre>
<p>We remove a column name from <em>column_list</em>:</p>
<pre>SELECT 1 a, 2 b, 3 c UNION CORRESPONDING BY(a, c) SELECT 4 a, 5 b, 6 c;
 a | c
---+---
 1 | 3
 4 | 6
(2 rows)</pre>
<p>Although we can suggest that CORRESPONDING BY is more useful with * queries as in:</p>
<pre>SELECT * FROM t1 UNION CORRESPONDING BY (a, b) SELECT * FROM t2;</pre>
<h3>Why</h3>
<p>There is a single main reason why I pursued to write a patch for CORRESPONDING in postgresql, I decided to delve into postgresql code base with a simple project and it was in the TODO list. As it turns out it is not simple, and I cannot go without the saying &quot;If it is in the TODO list, it ain&#8217;t simple&quot;.</p>
<h3>Development Environment</h3>
<p>After setting up a vmware virtual machine with Pardus Linux installed, complete all the updates and make sure you have at least the following software configuration.</p>
<ul>
<li><a href="http://www.pardus.org.tr/en" target="_blank">Pardus Linux</a> 2011.2 (kernel 2.6.37.6 i686 GNU/Linux) </li>
<li>gcc 4.5.3 (compiler) </li>
<li>flex 2.5.35 (lexer) </li>
<li>bison 2.4.3 (parser generator) </li>
<li>autotools </li>
<li>gdb </li>
<li>ccache (compiler cache) </li>
<li><a href="http://git-scm.com/" target="_blank">git</a> (version control) </li>
<li><a href="http://eclipse.org/cdt/" target="_blank">eclipse CDT</a> (IDE) </li>
</ul>
<p>For eclipse configuration please see: <a href="http://wiki.postgresql.org/wiki/Working_with_Eclipse">http://wiki.postgresql.org/wiki/Working_with_Eclipse</a></p>
<p>For other details about setting up an environment for postgresql development, please see <a href="http://wiki.postgresql.org/wiki/Developer_FAQ">http://wiki.postgresql.org/wiki/Developer_FAQ</a></p>
<h3>How</h3>
<p>In this section, we will touch to the very basics of postgres query execution relating to the execution of a set operation(UNION, INTERSECT, EXCEPT)</p>
<ol>
<li><strong>Parser</strong>
<ol>
<li><strong>Raw Parser</strong> – Generate a raw parse tree from the sql statement. </li>
<li><strong>Analyzer</strong> – Generate a query tree from a raw parse tree. (<strong>This is what we will modify mostly</strong>) </li>
</ol>
</li>
<li><strong>Optimizer</strong> – Choose an efficient plan. </li>
<li><strong>Executor</strong> – Execute the chosen plan. </li>
</ol>
<h3>How Exactly</h3>
<p>There are two simple paths of implementing the CORRESPONDING clause, one is modifying the query tree such that <em>query1 </em>and<em> query2 </em>are wrapped in subqueries, and the other is modifying the way that UNION works which is a big deal involving many parts of the code from analyzer to optimizer. We chose to implement it by modifying the query tree which I will describe in a moment.</p>
<ol>
<li>Modify parser to accept new syntax.
<ol>
<li>Introduce keywords. </li>
<li>Generate a relevant parse tree for the set operation. </li>
<li>Add metadata about CORRESPONDING operation to node structures in the raw parse tree. (column_list, is it CORRESPONDING or CORRESPONDING BY, etc.) </li>
</ol>
</li>
<li>Update analyzer to process the new syntax.
<ol>
<li>While processing the set operation, verify validity of the CORRESPONDING semantics.
<ol>
<li>Does the columns exist in both tables </li>
<li>Is there any non-existent column names in <em>column_list.</em> </li>
<li>Is output projection non-empty, etc. </li>
</ol>
</li>
<li>If CORRESPONDING clause is valid, modify <em>query1</em> and <em>query2.</em> </li>
</ol>
</li>
<li>Write documentation. </li>
<li>Write regressions. </li>
</ol>
<h5>New Syntax</h5>
<p>Modifying parser is the easiest part, you would think. What is the big deal? We are only going to add a keyword, what could go wrong? Well, keep on.</p>
<h6>backend/parser/gram.y</h6>
<p>gram.y is a bison grammar file. Bison produces a c file from this input. It&#8217;s syntax is intuitive and you will feel familiar if you check a few SQL statements you know by heart and inspect their gram.y counterparts. For the hasty it gram.y looks like this:</p>
<pre>GrantStmt:	GRANT <strong>privileges</strong> ON privilege_target TO grantee_list
			opt_grant_grant_option
				{
					GrantStmt *n = makeNode(GrantStmt);
					n-&gt;is_grant = true;
					n-&gt;privileges = $2;
					n-&gt;targtype = ($4)-&gt;targtype;
					n-&gt;objtype = ($4)-&gt;objtype;
					n-&gt;objects = ($4)-&gt;objs;
					n-&gt;grantees = $6;
					n-&gt;grant_option = $7;
					$$ = (Node*)n;
				}
		;</pre>
<p>Here, uppercase words are keywords, lower case words are further definitions. statement between {} is the raw parse tree description of GrantStmt. privileges, privilege_target, grantee_list, opt_grant_grant_option are defined below this definition of GrantStmt.</p>
<p>Between the curly braces, we refer to the positional arguments of the statement. </p>
<pre>n-&gt;privileges = $2;</pre>
<p>$2 refers to <strong>privileges </strong>in the first line for example.</p>
<h6>Adding CORRESPONDING to gram.y</h6>
<p>To use CORRESPONDING BY as a valid clause, we need to add CORRESPONDING and BY keywords to the parser. BY keyword is already used in GROUP BY, ORDER BY etc. so we only need to add CORRESPONDING token.</p>
<pre>
<pre class="brush: diff; title: ; notranslate">*** 498,504 ****
  	CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
  	CLUSTER COALESCE COLLATE COLLATION COLUMN COMMENT COMMENTS COMMIT
  	COMMITTED CONCURRENTLY CONFIGURATION CONNECTION CONSTRAINT CONSTRAINTS
! 	CONTENT_P CONTINUE_P CONVERSION_P COPY COST CREATE
  	CROSS CSV CURRENT_P
  	CURRENT_CATALOG CURRENT_DATE CURRENT_ROLE CURRENT_SCHEMA
  	CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
--- 499,505 ----
  	CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
  	CLUSTER COALESCE COLLATE COLLATION COLUMN COMMENT COMMENTS COMMIT
  	COMMITTED CONCURRENTLY CONFIGURATION CONNECTION CONSTRAINT CONSTRAINTS
! 	CONTENT_P CONTINUE_P CONVERSION_P COPY CORRESPONDING COST CREATE
  	CROSS CSV CURRENT_P
  	CURRENT_CATALOG CURRENT_DATE CURRENT_ROLE CURRENT_SCHEMA
  	CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE</pre>
</pre>
<p>Add CORRESPONDING to select statement as a valid clause.</p>
<pre>*** 8489,8507 ****
  					n-&gt;fromClause = list_make1($2);
  					$$ = (Node *)n;
  				}
! 			| select_clause UNION opt_all select_clause
  				{
! 					$$ = makeSetOp(SETOP_UNION, $3, $1, $4);
  				}
! 			| select_clause INTERSECT opt_all select_clause
  				{
! 					$$ = makeSetOp(SETOP_INTERSECT, $3, $1, $4);
  				}
! 			| select_clause EXCEPT opt_all select_clause
  				{
! 					$$ = makeSetOp(SETOP_EXCEPT, $3, $1, $4);
  				}
  		;

  /*
   * SQL standard WITH clause looks like:
--- 8490,8514 ----
  					n-&gt;fromClause = list_make1($2);
  					$$ = (Node *)n;
  				}
! 			| select_clause UNION opt_all <strong><font style="background-color: #ffff00">opt_corresponding_clause</font></strong> select_clause
  				{
! 					$$ = makeSetOp(SETOP_UNION, <strong>$3, $4, $1, $5</strong>);
  				}
! 			| select_clause INTERSECT opt_all <strong><font style="background-color: #ffff00">opt_corresponding_clause</font></strong> select_clause
  				{
! 					$$ = makeSetOp(SETOP_INTERSECT, <strong>$3, $4, $1, $5</strong>);
  				}
! 			| select_clause EXCEPT opt_all <font style="background-color: #ffff00"><strong>opt_corresponding_clause</strong></font> select_clause
  				{
! 					$$ = makeSetOp(SETOP_EXCEPT, <strong>$3, $4, $1, $5</strong>);
  				}
  		;</pre>
<p>Now we need to define <font style="background-color: #ffff00"><strong>opt_corresponding_clause</strong></font>.</p>
<pre> opt_corresponding_clause:
 			CORRESPONDING BY '(' expr_list ')'		{ $$ = $4; }
 			| CORRESPONDING							{ $$ = list_make1(NIL); }
 			| /*EMPTY*/								{ $$ = NIL; }
 			;</pre>
<p>We have modified the parameter list of makeSetOp. Let&#8217;s go over there.</p>
<pre>*** 12642,12648 ****
  }

  static Node *
<font color="#ff0000">! makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg)</font>
  {
  	SelectStmt *n = makeNode(SelectStmt);

--- 12649,12655 ----
  }

  static Node *
<font color="#0000ff">! makeSetOp(SetOperation op, bool all, List *correspondingClause, Node *larg, Node *rarg)
</font>  {
  	SelectStmt *n = makeNode(SelectStmt);

***************
*** 12650,12655 ****
--- 12657,12663 ----
  	n-&gt;all = all;
  	n-&gt;larg = (SelectStmt *) larg;
  	n-&gt;rarg = (SelectStmt *) rarg;
<font style="background-color: #ffff00" color="#000000">+ 	n-&gt;correspondingClause = correspondingClause;</font>
  	return (Node *) n;
  }</pre>
<p>Now we have used SelectStmt-&gt;correspondingClause, let&#8217;s add that to parsenodes.h</p>
<pre>include/nodes/parsenodes.h
***************
*** 1006,1011 ****
--- 1006,1013 ----
  	/*
  	 * These fields are used only in &quot;leaf&quot; SelectStmts.
  	 */
<font style="background-color: #ffff00">+ 	List	   *correspondingClause;  /* NULL, list of CORRESPONDING BY exprs, or */
+ 	 	 	 	 	 	 	 	/* lcons(NIL, NIL) for CORRESPONDING */</font></pre>
<p>Code will compile, but there is one tidbit missing. Postgres will shout an error to you about unrecognized keywords if you use a CORRESPONDING query.</p>
<p>You have to add all new keywords to kwlist.h</p>
<pre>*** 94,99 ****
--- 94,100 ----
  PG_KEYWORD(&quot;continue&quot;, CONTINUE_P, UNRESERVED_KEYWORD)
  PG_KEYWORD(&quot;conversion&quot;, CONVERSION_P, UNRESERVED_KEYWORD)
  PG_KEYWORD(&quot;copy&quot;, COPY, UNRESERVED_KEYWORD)
<font style="background-color: #ffff00" color="#000000">+ PG_KEYWORD(&quot;corresponding&quot;, CORRESPONDING, UNRESERVED_KEYWORD)</font>
  PG_KEYWORD(&quot;cost&quot;, COST, UNRESERVED_KEYWORD)
  PG_KEYWORD(&quot;create&quot;, CREATE, RESERVED_KEYWORD)
  PG_KEYWORD(&quot;cross&quot;, CROSS, TYPE_FUNC_NAME_KEYWORD)</pre>
<hr />
<p>At this point we can compile postgres and see that it dismisses the CORRESPONDING or CORRESPONDING BY from a query without an error.</p>
<h6>Adding meaning to CORRESPONDING, in analyze.c</h6>
<p>In <em>transformSetOperationTree</em> function, we determine the output column names, and verify their existence in tables of both sides. Here CORRESPONDING part is given. CORRESPONDING BY is similar.</p>
<pre>
<pre class="brush: cpp; title: ; notranslate"> 		else if(linitial(stmt-&amp;gt;correspondingClause) == NULL)
 		{
 			// CORRESPONDING clause, find matching column names from both tables. If there are none then it is a syntax error.

 			Query	*largQuery;
 			Query	*rargQuery;
 			List	*matchingColumns;

 			/* Analyze left query to resolve column names. */
 			largQuery = parse_sub_analyze((Node *) stmt-&amp;gt;larg, pstate, NULL, false);

 			/* Analyze right query to resolve column names. */
 			rargQuery = parse_sub_analyze((Node *) stmt-&amp;gt;rarg, pstate, NULL, false);

 			/* Find matching columns from both queries. */
 			matchingColumns = determineMatchingColumns(largQuery-&amp;gt;targetList,
 													   rargQuery-&amp;gt;targetList);

 			op-&amp;gt;correspondingColumns = matchingColumns;
 			op-&amp;gt;hasCorrespondingBy = false;

 			/* If matchingColumns is empty, there is an error. At least one column in the select lists must have the same name. */
 			if(list_length(matchingColumns) == 0)
 			{
 				ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),
 								errmsg(&amp;quot;%s queries with a CORRESPONDING clause must have at least one column with the same name&amp;quot;,
 								context)));
 			}

 			// Create subquery for larg, selecting column names from matchingColumns.
 			stmt-&amp;gt;larg = createSubqueryForCorresponding(matchingColumns, stmt-&amp;gt;larg);

 			// Assign newly generated query to original left query.
 			op-&amp;gt;larg = transformSetOperationTree(pstate, stmt-&amp;gt;larg,
 												 false,
 												 &amp;lt;argetlist);

 			// Create subquery for rarg, selecting column names from matchingColumns.
 			stmt-&amp;gt;rarg = createSubqueryForCorresponding(matchingColumns, stmt-&amp;gt;rarg);

 			// Assign newly generated query to original right query.
 			op-&amp;gt;rarg = transformSetOperationTree(pstate, stmt-&amp;gt;rarg,
 												 false,
 												 &amp;amp;rtargetlist);
 		}</pre>
</pre>
<p>To create a subquery with given column names and a query to me used as a subquery, we use <em>createSubqueryForCorresponding</em> function. This function returns a SelectStmt for the following statement:</p>
<pre>SELECT outputColumns FROM (main_arg)</pre>
<pre>
<pre class="brush: cpp; title: ; notranslate">  /*
  * Returns a subquery selecting outputColumns from main_arg.
  * main_arg is modified and returned.
  */
 static SelectStmt *
 createSubqueryForCorresponding(List* outputColumns, SelectStmt* main_arg)
 {
 	ColumnRef *cr;
 	ResTarget *rt;
 	SelectStmt *n;

 	RangeSubselect * rss;
 	ListCell* mctl;

 	n = makeNode(SelectStmt);
 	n-&amp;gt;targetList = NIL;
 	foreach(mctl, outputColumns)
 	{
 		TargetEntry *mctle = (TargetEntry *) lfirst(mctl);

 		cr = makeNode(ColumnRef);
 		cr-&amp;gt;fields = list_make1(makeString(mctle-&amp;gt;resname));
 		cr-&amp;gt;location = -1;

 		rt = makeNode(ResTarget);
 		rt-&amp;gt;name = NULL;
 		rt-&amp;gt;indirection = NIL;
 		rt-&amp;gt;val = (Node *)cr;
 		rt-&amp;gt;location = -1;

 		n-&amp;gt;targetList = lappend(n-&amp;gt;targetList, rt);
 	}

 	rss = makeNode(RangeSubselect);

 	// XXX makeAlias alias name should be empty??
 	rss-&amp;gt;alias = makeAlias(&amp;quot;&amp;quot;, NULL);
	rss-&amp;gt;subquery = (Node *)main_arg;

 	n-&amp;gt;fromClause = list_make1(rss);

 	main_arg = n;

 	return main_arg;
 }</pre>
</pre>
<h5>Documentation and Regression</h5>
<p>For documentation, please see changes in </p>
<ul>
<li>doc/src/sgml/queries.sgml </li>
<li>doc/src/sgml/sql.sgml </li>
</ul>
<p>For regression, please see the <a href="http://wiki.postgresql.org/wiki/Regression_test_authoring" target="_blank">excellent article</a> from postgresql, and see the changes in</p>
<ul>
<li>src/test/regress/sql/corresponding_union.sql </li>
<li>src/test/regress/serial_schedule </li>
<li>src/test/regress/parallel_schedule </li>
<li>src/test/regress/expected/corresponding_union.out </li>
</ul>
<h3>The (not) part</h3>
<p>This is the main reason the patch was not accepted by postgresql mailing list community. When we modify the parse tree in the analyzer.c, we modify it for good. Optimizer, planner, executor never sees a CORRESPONDING clause, they only see the subquery we generated.</p>
<pre>=# CREATE VIEW v1 AS <font style="background-color: #ffff00">SELECT 1 a, 2 b, 3 c UNION CORRESPONDING BY(a, c) SELECT 4 a, 5 b, 6 c</font>;
CREATE VIEW
=# select * from v1;
 a | c
---+---
 1 | 3
 4 | 6
(2 rows)

=# select * from pg_views WHERE viewname = 'v1';
 schemaname | viewname | viewowner |                                                                  definition
------------+----------+-----------+----------------------------------------------------------------------------------------------------------------------------------------------
 public     | v1       | kerem     | <font style="background-color: #ffff00">SELECT alias.a, alias.c FROM (SELECT 1 AS a, 2 AS b, 3 AS c) alias UNION SELECT alias.a, alias.c FROM (SELECT 4 AS a, 5 AS b, 6 AS c) alias</font>;
(1 row)</pre>
<h3>Patch File</h3>
<ul>
<li>Download: <a href="http://dissipatedHeat.com/wp-content/uploads/2011/11/corresponding_clause_v4.7z">corresponding_clause_v4.patch</a> Note: Base for the patch is git commit version <a href="https://github.com/postgres/postgres/commit/6f3dc00e24aa2a8e7e2c5e5095b6223712b8204c">6f3dc00</a>. </li>
<li>Mailing list reference: <a href="http://archives.postgresql.org/message-id/CAJZSWkWN3YwQ01C3+cq0+eyZ1DmK=69_6vryrsVGMC=+fWrSZA@mail.gmail.com">pgsql-hackers</a> </li>
</ul>
<img src="http://feeds.feedburner.com/~r/dheat/~4/lKg1b6KbOTg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://dissipatedHeat.com/2011/11/10/how-not-to-write-a-patch-for-postgresql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://dissipatedHeat.com/2011/11/10/how-not-to-write-a-patch-for-postgresql/</feedburner:origLink></item>
		<item>
		<title>KorTrans – UTM Koordinat ve Pafta (Android)</title>
		<link>http://feedproxy.google.com/~r/dheat/~3/jaMjhwO9XC0/</link>
		<comments>http://dissipatedHeat.com/2011/10/19/kortrans-utm-koordinat-ve-pafta-android/#comments</comments>
		<pubDate>Wed, 19 Oct 2011 20:10:40 +0000</pubDate>
		<dc:creator>Kerem Kat</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Harita]]></category>
		<category><![CDATA[Matematik]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[koordinat]]></category>
		<category><![CDATA[KorTrans]]></category>
		<category><![CDATA[Mercator]]></category>
		<category><![CDATA[pafta]]></category>
		<category><![CDATA[UTM]]></category>

		<guid isPermaLink="false">http://dissipatedHeat.com/?p=302</guid>
		<description><![CDATA[KorTrans &#8211; Koordinat Dönüşüm (Android) Android telefonları için UTM, Derece Dakika Saniye, Ondalık Derece koordinat dönüşüm programı. Android Market&#8217;ten indirmek için (ücretsiz): KorTrans aratabilir veya https://market.android.com/details?id=com.dissipatedheat.kortrans adresine doğrudan gidebilirsiniz. Desteklediği Koordinat Türleri: Universal Transverse Mercator (UTM, 6 derecelik, WGS84 datumu): 35T 555555 4600000 Derece Dakika Saniye (DDS, DMS): 41° 32&#8242; 59,05&#8243; K 27° 39&#8242; 58,08&#8243; D Ondalık <a href='http://dissipatedHeat.com/2011/10/19/kortrans-utm-koordinat-ve-pafta-android/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<h3>KorTrans &#8211; Koordinat Dönüşüm (Android)</h3>
<p>Android telefonları için UTM, Derece Dakika Saniye, Ondalık Derece koordinat dönüşüm programı.</p>
<p>Android Market&#8217;ten <strong>indirmek</strong> için (ücretsiz): <strong>KorTrans</strong> aratabilir veya <a href="https://market.android.com/details?id=com.dissipatedheat.kortrans" target="_blank">https://market.android.com/details?id=com.dissipatedheat.kortrans</a> adresine doğrudan gidebilirsiniz.</p>
<p>Desteklediği Koordinat Türleri:</p>
<ul>
<li>Universal Transverse Mercator (UTM, 6 derecelik, WGS84 datumu): <strong>35T 555555 4600000</strong></li>
<li>Derece Dakika Saniye (DDS, DMS): <strong>41° 32&#8242; 59,05&#8243; K 27° 39&#8242; 58,08&#8243; D</strong></li>
<li>Ondalık Derece (DD): <strong>41,549735 K 27,666134 D</strong></li>
</ul>
<p>Özellikler:</p>
<ul>
<li><strong>Pafta</strong> bulma.</li>
<li>Noktaları kaydedebilme</li>
<li>Kayıtlı noktalara simge, kod, not ve resim ekleyebilme.</li>
<li>Kayıtlı noktalar üzerinde manuel veya haritadan sürükleyerek oynama yapabilme</li>
<li>Kayıtlı noktaların resmini silebilme, değiştirebilme</li>
<li>Kayıtlı noktayı <strong>UTM</strong> veya DDS&#8217;ye dönüştürme</li>
<li>Kayıtlı noktaların tümünün koordinatlarını mail olarak gönderebilme</li>
<li>Koordinatları manuel girme</li>
<li>Haritadan nokta seçme</li>
<li>Haritadan nokta seçerken adrese göre arama (<strong>geocoding</strong>)</li>
<li>Haritadan seçilen noktanın adresini gösterme (<strong>reverse geocoding</strong>)</li>
<li><strong>GPS</strong> yardımıyla nokta seçme</li>
</ul>
<p>İleride Eklenecek Özellikler:</p>
<ul>
<li>KorTrans kullanıcı adı ve şifresi ile noktaları cloud&#8217;a kaydetme, gönderme.</li>
<li>Noktalardan poligon oluşturma, kaydetme.</li>
<li>Poligon koordinatlarını ruhsat başvurusu için mail atma.</li>
<li>Ruhsatların alanlarını görüntüleme.</li>
<li>GPS yardımıyla fiziksel olarak ruhsat sahasında olup olmadığınızın tespiti.</li>
</ul>
<h4><span style="direction: ltr;">Örnek Kullanım Videosu</span></h4>
<p>Ondalık Dereceden UTM&#8217;ye Dönüşüm:</p>
<p><object width="695" height="521"><param name="movie" value="http://www.youtube.com/v/Wni0AWLv3lk?version=3&#038;feature=oembed"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/Wni0AWLv3lk?version=3&#038;feature=oembed" type="application/x-shockwave-flash" width="695" height="521" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>UTM&#8217;den Derece Dakika Saniyeye Dönüşüm:</p>
<p><object width="695" height="521"><param name="movie" value="http://www.youtube.com/v/i3D6UHu73VI?version=3&#038;feature=oembed"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/i3D6UHu73VI?version=3&#038;feature=oembed" type="application/x-shockwave-flash" width="695" height="521" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>Haritadan Seçilen Noktanın Dönüşümü:</p>
<p><object width="695" height="521"><param name="movie" value="http://www.youtube.com/v/07Jd_GZiw40?version=3&#038;feature=oembed"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/07Jd_GZiw40?version=3&#038;feature=oembed" type="application/x-shockwave-flash" width="695" height="521" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>Kayıtlı Noktaları Mail Atma:</p>
<p><object width="695" height="521"><param name="movie" value="http://www.youtube.com/v/B4biZAfCQr0?version=3&#038;feature=oembed"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/B4biZAfCQr0?version=3&#038;feature=oembed" type="application/x-shockwave-flash" width="695" height="521" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<img src="http://feeds.feedburner.com/~r/dheat/~4/jaMjhwO9XC0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://dissipatedHeat.com/2011/10/19/kortrans-utm-koordinat-ve-pafta-android/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://dissipatedHeat.com/2011/10/19/kortrans-utm-koordinat-ve-pafta-android/</feedburner:origLink></item>
		<item>
		<title>Çarpanlarına Bölümünün Kalanı Verilmiş Polinoma Bölümden Kalan (Muhteşem Başlık)</title>
		<link>http://feedproxy.google.com/~r/dheat/~3/iOFRb8xeMvI/</link>
		<comments>http://dissipatedHeat.com/2011/10/14/carpanlarina-bolumun-kalani-verilmis-polinoma-bolumunden-kalan/#comments</comments>
		<pubDate>Fri, 14 Oct 2011 20:38:36 +0000</pubDate>
		<dc:creator>Kerem Kat</dc:creator>
				<category><![CDATA[Matematik]]></category>
		<category><![CDATA[polinom]]></category>

		<guid isPermaLink="false">http://dissipatedHeat.com/?p=285</guid>
		<description><![CDATA[Bir Polinomu İkinci Derece Başka Bir Polinoma Bölmede Kalan Matematik ve polinomlar ile ilgili bu yazımızda karşılaşılan bir problemin analitik çözümüne kısaca değineceğiz. Polinom kalan teoremine göre, P(x) polinomunun (x-a) binomuna bölümünden kalan, P(a)&#8217;dır. Diğer bir deyişle: P(x) polinomunun (x-a) binomuna bölümünden kalan A, (x-b) binomuna bölümünden kalan B olsun. Bizden istenen P(x) polinomunun, (x-a)(x-b) <a href='http://dissipatedHeat.com/2011/10/14/carpanlarina-bolumun-kalani-verilmis-polinoma-bolumunden-kalan/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<h3>Bir Polinomu İkinci Derece Başka Bir Polinoma Bölmede Kalan</h3>
<p>Matematik ve polinomlar ile ilgili bu yazımızda karşılaşılan bir problemin analitik çözümüne kısaca değineceğiz.</p>
<p><a href="http://en.wikipedia.org/wiki/Polynomial_remainder_theorem" target="_blank">Polinom kalan teoremine</a> göre, P(x) polinomunun (x-a) binomuna bölümünden kalan, P(a)&#8217;dır. Diğer bir deyişle:</p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="P(x) = (x-a)\cdot Q(x) + P(a)" alt="Polinom bölme." src="http://www.codecogs.com/eq.latex?P(x) = (x-a)\cdot Q(x) + P(a)" /></p>
<p>P(x) polinomunun (x-a) binomuna bölümünden kalan A, (x-b) binomuna bölümünden kalan B olsun.</p>
<p>Bizden istenen P(x) polinomunun, (x-a)(x-b) polinomuna bölümünden kalandır. Problemi kısaca ifade edelim:</p>
<p><span id="more-285"></span>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="a,b,A,B \in \mathbb{R} \\ A = P(a) \\ B=P(b) \\ P(x) = (x-a) \cdot (x-b) \cdot Q(x) +K(x) \\ \deg(K(x)) = 1 \\ K(x) = ?" alt="Polinom bölme." src="http://www.codecogs.com/eq.latex?a,b,A,B \in \mathbb{R} \\ A = P(a) \\ B=P(b) \\ P(x) = (x-a) \cdot (x-b) \cdot Q(x) +K(x) \\ \deg(K(x)) = 1 \\ K(x) = ?" /></p>
<p>Bildiklerimizi yerlerine koyalım:</p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="A = P(a) = (a-a) \cdot (a-b) \cdot Q(x) + K(a) = K(a)" alt="A = P(a) = (a-a) \cdot (a-b) \cdot Q(x) + K(a) = K(a)" src="http://www.codecogs.com/eq.latex?A = P(a) = (a-a) \cdot (a-b) \cdot Q(x) + K(a) = K(a)" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="B = P(b) = (b-a) \cdot (b-b) \cdot Q(x) + K(b) = K(b)" alt="B = P(b) = (b-a) \cdot (b-b) \cdot Q(x) + K(b) = K(b)" src="http://www.codecogs.com/eq.latex?B = P(b) = (b-a) \cdot (b-b) \cdot Q(x) + K(b) = K(b)" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="\deg(K(x)) = 1 \implies K(x) = m \cdot x + n \ni m,n \in \mathbb{R}" alt="\deg(K(x)) = 1 \implies K(x) = m \cdot x + n \ni m,n \in \mathbb{R}" src="http://www.codecogs.com/eq.latex?\deg(K(x)) = 1 \implies K(x) = m \cdot x + n \ni m,n \in \mathbb{R}" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="A = m \cdot a + n" alt="A = m \cdot a + n" src="http://www.codecogs.com/eq.latex?A = m \cdot a + n" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="B = m \cdot b + n" alt="B = m \cdot b + n" src="http://www.codecogs.com/eq.latex?B = m \cdot b + n" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="A - B = m \cdot (a - b)" alt="A - B = m \cdot (a - b)" src="http://www.codecogs.com/eq.latex?A - B = m \cdot (a - b)" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="m = \frac{A-B}{a-b}" alt="m = \frac{A-B}{a-b}" src="http://www.codecogs.com/eq.latex?m = \frac{A-B}{a-b}" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="b \cdot A = m \cdot a \cdot b + b \cdot n" alt="b \cdot A = m \cdot a \cdot b + b \cdot n" src="http://www.codecogs.com/eq.latex?b \cdot A = m \cdot a \cdot b + b \cdot n" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="a \cdot B = m \cdot a \cdot b + a \cdot n" alt="a \cdot B = m \cdot a \cdot b + a \cdot n" src="http://www.codecogs.com/eq.latex?a \cdot B = m \cdot a \cdot b + a \cdot n" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="b \cdot A - a \cdot B = n \cdot (b-a)" alt="b \cdot A - a \cdot B = n \cdot (b-a)" src="http://www.codecogs.com/eq.latex?b \cdot A - a \cdot B = n \cdot (b-a)" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="n = \frac{b \cdot A - a \cdot B}{b-a}" alt="n = \frac{b \cdot A - a \cdot B}{b-a}" src="http://www.codecogs.com/eq.latex?n = \frac{b \cdot A - a \cdot B}{b-a}" /></p>
<h4>Sonuç</h4>
<p>Aşağıdakine benzer bir formülü tüm çabalarım neticesinde googleda bula<strong>ma</strong>dım, belki de ne yazacağımı bilemediğimdendir&#8230;</p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="K(x) = \frac{A-B}{a-b} \cdot x + \frac{a \cdot B - b \cdot A}{a-b}" alt="K(x) = \frac{A-B}{a-b} \cdot x + \frac{a \cdot B - b \cdot A}{a-b}" src="http://www.codecogs.com/eq.latex?K(x) = \frac{A-B}{a-b} \cdot x + \frac{a \cdot B - b \cdot A}{a-b}" /></p>
<h4>Örnek</h4>
<p>P(x) polinomunun (x+2) binomuna bölümünden kalan 3, (x-4) binomuna bölümünden kalan -9&#8242;dir. P(x)&#8217;in (x+2)(x-4) polinomuna bölümünden kalan nedir?</p>
<p>Verilenler:</p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="a = -2" alt="a = -2" src="http://www.codecogs.com/eq.latex?a = -2" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="b = 4" alt="b = 4" src="http://www.codecogs.com/eq.latex?b = 4" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="A = 3" alt="A = 3" src="http://www.codecogs.com/eq.latex?A = 3" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="B = -9" alt="B = -9" src="http://www.codecogs.com/eq.latex?B = -9" /></p>
<p>Formülümüzde yerine koyalım:</p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="K(x) = \frac{3- (-9)}{-2-4} \cdot x + \frac{(-2) \cdot (-9) - 4 \cdot 3}{ -2-4 }" alt="K(x) = \frac{3- (-9)}{-2-4} \cdot x + \frac{(-2) \cdot (-9) - 4 \cdot 3}{ -2-4 }" src="http://www.codecogs.com/eq.latex?K(x) = \frac{3- (-9)}{-2-4} \cdot x + \frac{(-2) \cdot (-9) - 4 \cdot 3}{ -2-4 }" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="K(x) = \frac{12}{-6} \cdot x + \frac{18-12}{-6}" alt="K(x) = \frac{12}{-6} \cdot x + \frac{18-12}{-6}" src="http://www.codecogs.com/eq.latex?K(x) = \frac{12}{-6} \cdot x + \frac{18-12}{-6}" /></p>
<p style="text-align: center"><img style="background-color: white" class="aligncenter" title="K(x) = -2 \cdot x - 1" alt="K(x) = -2 \cdot x - 1" src="http://www.codecogs.com/eq.latex?K(x) = -2 \cdot x - 1" /></p>
<img src="http://feeds.feedburner.com/~r/dheat/~4/iOFRb8xeMvI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://dissipatedHeat.com/2011/10/14/carpanlarina-bolumun-kalani-verilmis-polinoma-bolumunden-kalan/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://dissipatedHeat.com/2011/10/14/carpanlarina-bolumun-kalani-verilmis-polinoma-bolumunden-kalan/</feedburner:origLink></item>
		<item>
		<title>CPU üzerinde Connected Component Labeling (CCL)</title>
		<link>http://feedproxy.google.com/~r/dheat/~3/uPjSeHiOJi8/</link>
		<comments>http://dissipatedHeat.com/2011/07/19/cpu-uzerinde-connected-component-labeling-ccl/#comments</comments>
		<pubDate>Tue, 19 Jul 2011 07:15:14 +0000</pubDate>
		<dc:creator>Kerem Kat</dc:creator>
				<category><![CDATA[CUDA]]></category>
		<category><![CDATA[Görüntü İşleme]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[Matematik]]></category>
		<category><![CDATA[OpenCV]]></category>
		<category><![CDATA[C]]></category>

		<guid isPermaLink="false">http://dissipatedHeat.com/?p=258</guid>
		<description><![CDATA[Önceki CUDA ile OpenCV kullanarak Webcam Görüntü İşleme yazımızda bahsedilen projeye ekleme bir filtre olarak gerçekleştirilen Connected Component Labeling (Birleşik Eleman Etiketleme) filtresini OpenCV ile webcam görüntü işlemede nasıl kullandığımıza bakalım. NOT: Bu yazıdaki kod örnekleri kısaltılarak verilmiştir. Kod belgeleri için Doxygen ile yaratılmış olan mikrositeyi inceleyebilirsiniz (yazıdaki eklemeleri içerecek şekilde güncellenmiştir). NOT: Her tür <a href='http://dissipatedHeat.com/2011/07/19/cpu-uzerinde-connected-component-labeling-ccl/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Önceki <a href="http://dissipatedheat.com/2011/05/29/cuda-ile-opencv-kullanarak-webcam-goruntu-isleme/">CUDA ile OpenCV kullanarak Webcam Görüntü İşleme</a> yazımızda bahsedilen projeye ekleme bir filtre olarak gerçekleştirilen Connected Component Labeling (Birleşik Eleman Etiketleme) filtresini OpenCV ile webcam görüntü işlemede nasıl kullandığımıza bakalım.</p>
<p>NOT: Bu yazıdaki kod örnekleri kısaltılarak verilmiştir. Kod belgeleri için <a href="http://www.stack.nl/~dimitri/doxygen/index.html">Doxygen</a> ile yaratılmış olan mikrositeyi <a href="http://dissipatedheat.com/doxygen/imageFilterLib/annotated.html">inceleyebilirsiniz</a> (yazıdaki eklemeleri içerecek şekilde güncellenmiştir).</p>
<p>NOT: Her tür fikir, öneri ve eleştirinizi yorumlara yazabilirsiniz, teşekkür ederiz.</p>
<h2>İçindekiler</h2>
<ul>
<li>Gerekenler</li>
<li>CCL Nedir?</li>
<li>CCL için Önişleme</li>
<li>CPU CCL Filtresi: <code>CpuCCLFilter</code></li>
<li>Filtre Örnekleri</li>
<li>İndirmeler</li>
</ul>
<h2>Gerekenler</h2>
<ul>
<li>VS 2010 ve C/C++ Bilgisi</li>
<li>OpenCV ile görüntü yakalama aşinalığı. Windows için OpenCV 2.2&#8242;yi patchlemeyi unutmayın! Önceki yazımızı <a href="http://dissipatedheat.com/2011/04/24/opencv-ile-webcam-goruntusu-isleme/">inceleyebilirsiniz</a>.</li>
<li>VS2010 ile CUDA projesi yaratabilmek. Önceki yazımızı <a href="http://dissipatedheat.com/2011/03/27/visual-studio-2010-ile-cuda-sdk-3-2-projesi-yaratmak/">inceleyebilirsiniz</a>.</li>
<li>CUDA içeren kodları çalıştırabilmek için CUDA destekli bir ekran kartı.</li>
<li>Derleyici includeları, libraryleri ve hataları ile uğraşmak için bolca sabır.</li>
<li>Önceki yazımızda detayları bulabilirsiniz: <a href="http://dissipatedheat.com/2011/05/29/cuda-ile-opencv-kullanarak-webcam-goruntu-isleme/">CUDA ile OpenCV kullanarak Webcam Görüntü İşleme</a></li>
</ul>
<h2>CCL Nedir?</h2>
<p>Connected Components Labeling, görüntüde birleşik olan nesneleri etiketleyerek birbirinden ayırdedebilecek hale getiren algoritmaya verilen addır. Burada en önemli tanım, &#8220;görüntüde birleşik&#8221; tamlamasıdır. Bu filtredeki kodlar, wikipediadaki <a href="http://en.wikipedia.org/wiki/Connected_Component_Labeling#Algorithms">CCL</a> açıklamasından yola çıkılarak yazılmıştır.</p>
<p>Görüntünün birleşik olması, komşu piksellerin renklerinin aynı veya belli bir derecede yakın olması ile ölçülür. Komşulukları gözönüne alırken 4-komşu ve 8-komşu modelleri kullanılabilir. 4-komşu modeli, ana yönler olan kuzey, güney, doğu ve batı komşularıdır. 8-komşu modelinde ara yönlerdeki komşular da hesaba katılır.</p>
<p><span id="more-258"></span><br />
<div id="attachment_262" class="wp-caption aligncenter" style="width: 160px"><a href="http://dissipatedHeat.com/wp-content/uploads/2011/07/4-komsu.png"><img class="size-thumbnail wp-image-262" title="4-komsu" src="http://dissipatedHeat.com/wp-content/uploads/2011/07/4-komsu-150x150.png" alt="" width="150" height="150" /></a><p class="wp-caption-text">4-komşuluk</p></div></p>
<div id="attachment_263" class="wp-caption aligncenter" style="width: 160px"><a href="http://dissipatedHeat.com/wp-content/uploads/2011/07/8-komsu.png"><img class="size-thumbnail wp-image-263" title="8-komsu" src="http://dissipatedHeat.com/wp-content/uploads/2011/07/8-komsu-150x150.png" alt="" width="150" height="150" /></a><p class="wp-caption-text">8-komşuluk</p></div>
<h2>CCL için Önişleme</h2>
<h3>Renk Benzerliği</h3>
<p>Renk benzerliği, CCL filtremizde birbiri ile aynı olarak nitelendirilecek renkleri ayırdetmemize yarar. Basit olarak gri skala uzayında uzaklığı 10&#8242;dan küçük olan renkler aynı sayıldı. Standart bir webcamin yakaladığı görüntülerde (en azından benimkinde) RGB noise denilen her renkten gürültü vardır. Webcam sabit bir yere bakarken ve görüntüde hiç hareket yokken bile yakalanan resmin pikselleri kısıtlı bir aralıkta sürekli değişir. Renklerin aynı olmasını katı bir şekilde gerektirmeyerek saptanan etiket sayısını düşürüyoruz, bir bakıma bu gürültüye bağışıklık kazanıyoruz.</p>
<h3>Thresholding</h3>
<p>Thresholding, belli bir aralığa sahip değeri, iki adet değere indirgemenin bir yoludur. Örneğin değerimiz 0 ile 255 arasında ise, threshold değerimiz 90 ise, 90&#8242;dan küçük değerler 0, büyük ve eşit değerler 1 grubuna denk gelir. CCL, threshold işlemi görmüş görüntü üzerinde çalışır. CCL algoritması için 0 arkaplan, 1 nesne demektir.</p>
<h2>CPU CCL Filtresi: <code>CpuCCLFilter</code></h2>
<p><code>ISingleImageFilter</code> arayüzünü kullanarak yazılan filtrede en önemli metod olan findConnectedComponents kısaca anlatılarak gösterilmiştir.</p>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/07/HelloOpenCV-2.png"><img class="aligncenter size-large wp-image-266" title="CCL Filtresi" src="http://dissipatedHeat.com/wp-content/uploads/2011/07/HelloOpenCV-2-1024x717.png" alt="" width="640" height="448" /></a></p>
<pre>
<pre class="brush: cpp; title: ; notranslate">/**
	\ref ptKernelLauncher tipinde metod.

	\param width Görüntünün piksel olarak genişliği
	\param height Görüntünün piksel olarak yüksekliği
	\param rowStride Görüntünün hafızadaki byte olarak genişliği.
	\param imageData Görüntü verisi.
	\param outImageData Etiket görüntü verisi.
	\param outLabelBitmap Etiket integer bitmap.

	Görüntüdeki birleşmiş birimleri bulur. Connected Component Labeler.
*/
template&lt;bool eightConnected&gt;
void CpuCCLFilter::findConnectedComponents(int width, int height, int rowStride, char* imageData, char* outImageData, int* outLabelBitmap)
{
	// label bitmap	

	// disjoint set için tip ve map tanımları.
	typedef std::map&lt;short, std::size_t&gt; rank_t; // element order.
	typedef std::map&lt;short, short&gt; parent_t;

	rank_t rank_map;
	parent_t parent_map;

	boost::associative_property_map&lt;rank_t&gt;   rank_pmap( rank_map );
	boost::associative_property_map&lt;parent_t&gt; parent_pmap( parent_map );

	// disjoint sets yaratılır.
	boost::disjoint_sets&lt;boost::associative_property_map&lt;rank_t&gt;, boost::associative_property_map&lt;parent_t&gt;&gt;
		ds( rank_pmap, parent_pmap );

	boost::unordered_set&lt;short&gt; elements;

	short labelNumber = 0;

	for(int i = 0; i &lt; height; i++)
	{
		for(int j = 0; j &lt; width; j++)
		{
			outLabelBitmap[i*rowStride + j] = 0;
		}
	}

	// tüm pikseller gezilir
	for(int i = 0; i &lt; height; i++)
	{
		for(int j = 0; j &lt; width; j++)
		{
			// if pixel is not background.
			if( imageData[i*rowStride + j] != 0 )
			{
				if(j &gt; 0 &amp; i &gt; 0 &amp;
					isSameColor( imageData[i*rowStride + j - 1], imageData[(i - 1)*rowStride + j]) // same value
					&amp; isSameColor( imageData[i*rowStride + j - 1], imageData[i*rowStride + j] )
				)
				{
					// west ve north aynı
					ds.union_set( outLabelBitmap[i*rowStride + j - 1], outLabelBitmap[(i - 1)*rowStride + j] );
					outLabelBitmap[i*rowStride + j] = outLabelBitmap[i*rowStride + j - 1];
				}

				if(j==0 &amp; i &gt; 0 &amp; isSameColor( imageData[i*rowStride + j], imageData[(i - 1)*rowStride + j] ))
				{
					outLabelBitmap[i*rowStride + j] = outLabelBitmap[(i-1)*rowStride + j];
				}

				// West pixel
				if(j &gt; 0 &amp; isSameColor( imageData[i*rowStride + j - 1], imageData[i*rowStride + j] ))
				{
					// west pixel ile aynı label.
					outLabelBitmap[i*rowStride + j] = outLabelBitmap[i*rowStride + j - 1];
				}

				// west farklı north aynı.
				if(
					(j &gt; 0 &amp; !isSameColor( imageData[i*rowStride + j - 1], imageData[i*rowStride + j] )) // west different value
					&amp; (i &gt; 0 &amp; isSameColor( imageData[(i-1)*rowStride + j], imageData[i*rowStride + j] )) // north same value
				)
				{
					// north ile aynı
					outLabelBitmap[i*rowStride + j] = outLabelBitmap[(i-1)*rowStride + j];
				}

				// west ve north farklı
				if(   ((j &gt; 0 &amp;;amp;&amp; !isSameColor( imageData[i*rowStride + j - 1], imageData[i*rowStride + j] )) || j == 0) // west different value
					&amp; ((i &gt; 0 &amp; !isSameColor( imageData[(i-1)*rowStride + j], imageData[i*rowStride + j] )) || i == 0) // north different value
				)
				{
					labelNumber++;
					ds.make_set(labelNumber);
					elements.insert(labelNumber);
					outLabelBitmap[i*rowStride + j] = labelNumber;
				}

				// northeast ve northwest kontrol edilir. (çaprazlar).
				if(eightConnected)
				{
					// northwest
					if(j &gt; 0 &amp; i &gt; 0
						&amp; isSameColor( imageData[(i-1)*rowStride + j - 1], imageData[i*rowStride + j] )
					)
					{
						// northwest ile aynı
						ds.union_set( outLabelBitmap[(i-1)*rowStride + j - 1], outLabelBitmap[i*rowStride + j] );
					}

					// northeast
					if(j+1 &lt; width &amp; i &gt; 0
						&amp; isSameColor( imageData[(i-1)*rowStride + j + 1], imageData[i*rowStride + j] )
					)
					{
						// northeast ile aynı
						ds.union_set( outLabelBitmap[(i-1)*rowStride + j + 1], outLabelBitmap[i*rowStride + j] );
					}
				}
			}
		}
	}

	int cnt = ds.count_sets(elements.begin(), elements.end());

	printf(&quot;Component count: %i\n&quot;, cnt);

	// second pass - label output image and colorize.
	for(int i = 0; i &lt; height; i++)
	{
		for(int j = 0; j &lt; width; j++)
		{
			int labelNo = ds.find_set( outLabelBitmap[i*rowStride + j] ); // pikselin etiketi bulunur.
			int R =0, G=0, B=0;

			// etiketler renklendirilir.
			hsl_to_rgb( 1.0f * labelNo / labelNumber, .8f + .2f * labelNo / labelNumber, .75f, &amp;R, &amp;G, &amp;B );

			int idx = i * rowStride + j;

			outImageData[idx * 3 + 0] = (char)(B);
			outImageData[idx * 3 + 1] = (char)(G);
			outImageData[idx * 3 + 2] = (char)(R);
		}
	}
}</pre>
</pre>
<h2>Filtre Örnekleri</h2>
<p><code>CpuCCLFilter</code>:<br />
<a href="http://dissipatedHeat.com/wp-content/uploads/2011/07/filterexample.png"><img class="aligncenter size-large wp-image-268" title="filterexample" src="http://dissipatedHeat.com/wp-content/uploads/2011/07/filterexample-1024x405.png" alt="" width="640" height="253" /></a></p>
<h3><a style="text-decoration: none;" name="indirmeler">İndirmeler</a></h3>
<p><strong>Dosyalar <a href="http://www.7-zip.org">7-zip</a> ile sıkıştırılmıştır.</strong></p>
<ul>
<li>Proje Kodları: <a href="http://dissipatedHeat.com/wp-content/uploads/2011/07/ImageFilterLib-with-CCL-HelloOpenCV.7z">ImageFilterLib &#8211; CCL &#8211; HelloOpenCV</a></li>
<li><a href="http://dissipatedheat.com/doxygen/imageFilterLib/inherits.html">Doxygen Belgeleri Mikrositesi</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/dheat/~4/uPjSeHiOJi8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://dissipatedHeat.com/2011/07/19/cpu-uzerinde-connected-component-labeling-ccl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://dissipatedHeat.com/2011/07/19/cpu-uzerinde-connected-component-labeling-ccl/</feedburner:origLink></item>
		<item>
		<title>UTM Koordinatlar ve Türkiye Paftaları</title>
		<link>http://feedproxy.google.com/~r/dheat/~3/2aE-d1C2tfc/</link>
		<comments>http://dissipatedHeat.com/2011/06/16/utm-koordinatlar-ve-turkiye-paftalari/#comments</comments>
		<pubDate>Thu, 16 Jun 2011 19:11:14 +0000</pubDate>
		<dc:creator>Kerem Kat</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Genel]]></category>
		<category><![CDATA[Harita]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Dönüşüm]]></category>
		<category><![CDATA[İzdüşüm]]></category>
		<category><![CDATA[koordinat]]></category>
		<category><![CDATA[Matematik]]></category>
		<category><![CDATA[Mercator]]></category>
		<category><![CDATA[pafta]]></category>
		<category><![CDATA[paftalar]]></category>
		<category><![CDATA[Projection]]></category>
		<category><![CDATA[silverlight]]></category>
		<category><![CDATA[UTM]]></category>

		<guid isPermaLink="false">http://dissipatedHeat.com/?p=248</guid>
		<description><![CDATA[Koordinat Dönüşümü ve Paftalar Serbestçe kullanabileceğiniz bir silverlight uygulaması olan KorTrans SL v1.0&#8242;a bu linkten erişebilirsiniz. Tüm Türkiye&#8217;deki paftaları, haritadan nokta seçerek bulabilirsiniz. UTM, Derece-Dakika-Saniye ve Ondalıklı Derece sistemleri arasında dönüşüm yapabilirsiniz. Pafta ismini &#8220;İSTANBUL-F22-b3&#8243; veya &#8220;F22-b3&#8243; şeklinde girerek de paftayı bulabilirsiniz. Seçilen pafta üzerinde UTM grid çizgilerini gösterebilirsiniz. Ölçeğinize göre belirlenen komşu paftaları görebilirsiniz.Her <a href='http://dissipatedHeat.com/2011/06/16/utm-koordinatlar-ve-turkiye-paftalari/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<h2>Koordinat Dönüşümü ve Paftalar</h2>
<p>Serbestçe kullanabileceğiniz bir silverlight uygulaması olan <a href="http://www.dissipatedheat.com/kortrans">KorTrans SL v1.0&#8242;a bu linkten</a> erişebilirsiniz.</p>
<ul>
<li>Tüm Türkiye&#8217;deki paftaları, haritadan nokta seçerek bulabilirsiniz.</li>
<li>UTM, Derece-Dakika-Saniye ve Ondalıklı Derece sistemleri arasında dönüşüm yapabilirsiniz.</li>
<li>Pafta ismini &#8220;İSTANBUL-F22-b3&#8243; veya &#8220;F22-b3&#8243; şeklinde girerek de paftayı bulabilirsiniz.</li>
<li>Seçilen pafta üzerinde UTM grid çizgilerini gösterebilirsiniz.</li>
<li>Ölçeğinize göre belirlenen komşu paftaları görebilirsiniz.Her zamanki gibi değerli yorumlarınızı bekliyoruz.</li>
</ul>
<p>Program silverlight ile çalışır. Silverlight, Microsoft&#8217;un bir platformudur, yüklemek çok kolaydır.</p>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/06/KorTransSL.png"><img class="aligncenter size-large wp-image-255" title="KorTrans SL" src="http://dissipatedHeat.com/wp-content/uploads/2011/06/KorTransSL-1024x730.png" alt="KorTrans SL" width="640" height="456" /></a></p>
<h2>Kullanım</h2>
<p>Programda markeri sürükleyerek koordinatı belirlersiniz.</p>
<p>Not: Sol üst köşedeki dönüşüm fonksiyonlarını denemeyi unutmayın!</p>
<h2>Linkler</h2>
<p>KorTrans SL: <a href="http://www.dissipatedheat.com/kortrans">http://www.dissipatedheat.com/kortrans</a>.</p>
<img src="http://feeds.feedburner.com/~r/dheat/~4/2aE-d1C2tfc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://dissipatedHeat.com/2011/06/16/utm-koordinatlar-ve-turkiye-paftalari/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://dissipatedHeat.com/2011/06/16/utm-koordinatlar-ve-turkiye-paftalari/</feedburner:origLink></item>
		<item>
		<title>CUDA ile OpenCV kullanarak Webcam Görüntü İşleme</title>
		<link>http://feedproxy.google.com/~r/dheat/~3/r0Xmkhr_Ec4/</link>
		<comments>http://dissipatedHeat.com/2011/05/29/cuda-ile-opencv-kullanarak-webcam-goruntu-isleme/#comments</comments>
		<pubDate>Sun, 29 May 2011 16:24:41 +0000</pubDate>
		<dc:creator>Kerem Kat</dc:creator>
				<category><![CDATA[CUDA]]></category>
		<category><![CDATA[Genel]]></category>
		<category><![CDATA[Matematik]]></category>
		<category><![CDATA[OpenCV]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Görüntü İşleme]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[nVidia]]></category>
		<category><![CDATA[webcam]]></category>

		<guid isPermaLink="false">http://dissipatedHeat.com/?p=158</guid>
		<description><![CDATA[For English version: http://www.codeproject.com/KB/GPU-Programming/opencv-cuda-filters.aspx Biraz uzun soluklu olan bu yazımıza OpenCV ve CUDA hakkında kısa maddeler ile başlayalım. NOT: Bu yazıdaki kod örnekleri kısaltılarak verilmiştir. Kod belgeleri için Doxygen ile yaratılmış olan mikrositeyi inceleyebilirsiniz. NOT: Her tür eleştirinizi yorumlara yazabilirsiniz, teşekkür ederiz. İçindekiler Gerekenler Görüntü İşleme ve Webcam ISingleImageFilter Kullanımı En basit filtre: IdentityFilter CPU <a href='http://dissipatedHeat.com/2011/05/29/cuda-ile-opencv-kullanarak-webcam-goruntu-isleme/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>For English version: <a href="http://www.codeproject.com/KB/GPU-Programming/opencv-cuda-filters.aspx">http://www.codeproject.com/KB/GPU-Programming/opencv-cuda-filters.aspx</a></p>
<p>Biraz uzun soluklu olan bu yazımıza OpenCV ve CUDA hakkında kısa maddeler ile başlayalım.</p>
<p>NOT: Bu yazıdaki kod örnekleri kısaltılarak verilmiştir. Kod belgeleri için <a href="http://www.stack.nl/~dimitri/doxygen/index.html">Doxygen</a> ile yaratılmış olan mikrositeyi <a href="http://dissipatedheat.com/doxygen/imageFilterLib/annotated.html">inceleyebilirsiniz</a>.</p>
<p>NOT: Her tür eleştirinizi yorumlara yazabilirsiniz, teşekkür ederiz.</p>
<h2>İçindekiler</h2>
<ul>
<li>Gerekenler</li>
<li>Görüntü İşleme ve Webcam</li>
<li>ISingleImageFilter Kullanımı</li>
<li>En basit filtre: IdentityFilter</li>
<li>CPU Üzerinde Negatif Görüntü Filtresi</li>
<li>Yeniden Hoşgeldin CUDA!</li>
<li>Görüntü Negatifi – CUDA</li>
<li>Texturelar</li>
<li>Görüntü Negatifi – CUDA Texture</li>
<li>Filtre Zinciri: SingleImageFilterChain</li>
<li>UML Şeması</li>
<li>Filtre Örnekleri</li>
</ul>
<h2>Gerekenler</h2>
<ul>
<li>VS 2010 ve C/C++ Bilgisi</li>
<li>OpenCV ile görüntü yakalama aşinalığı. Windows için OpenCV 2.2&#8242;yi patchlemeyi unutmayın! Önceki yazımızı <a href="http://dissipatedheat.com/2011/04/24/opencv-ile-webcam-goruntusu-isleme/">inceleyebilirsiniz</a>.</li>
<li>VS2010 ile CUDA projesi yaratabilmek. Önceki yazımızı <a href="http://dissipatedheat.com/2011/03/27/visual-studio-2010-ile-cuda-sdk-3-2-projesi-yaratmak/">inceleyebilirsiniz</a>.</li>
<li>CUDA içeren kodları çalıştırabilmek için CUDA destekli bir ekran kartı.</li>
<li>Derleyici includeları, libraryleri ve hataları ile uğraşmak için bolca sabır.</li>
</ul>
<h2>OpenCV Nedir?</h2>
<p><a href="http://opencv.willowgarage.com">OpenCV</a>, açık kaynaklı bir bilgisayarlı görselleştirme kütüphanesidir. Amacı görüntü işleme ve görselleştirmede sık kullanılan metodların kolaylıkla erişilebilir olmasını sağlamaktadır. </p>
<h2>CUDA Nedir?</h2>
<p><a href="http://www.nvidia.com/cuda">CUDA</a>, Compute-Unified Device Architecture, hesaplamaların grafik işlemcisi üzerinde gerçekleştirilmesi amacıyla CPU&#8217;dan zaman bağımsız olarak ve yüzlerce çekirdek üzerinde binlerce thread kullanarak paralel hesaplamaya olanak veren nVidia&#8217;nın bir kaç senedir satışa sunulan ekran kartlarında uyguladığı bir mimaridir. Bu muazzam paralellik(massively parallel) bize doğru kullanıldığında hesaplamada hız olarak dönecektir.</p>
<h2>Görüntü İşleme ve Webcam</h2>
<p>Görüntü işleme, görüntüye uygulanan matematiksel bir işlemi ifade eder. Örneğin görüntünün negatifinin alınması, görüntünün 90 derece çevrilmesi, görüntünün bir kurala göre bulandırılması vb. basit görüntü işleme metodlarıdır. Bir önceki yazımızda bahsettiğimiz <a href="http://dissipatedheat.com/2011/04/24/opencv-ile-webcam-goruntusu-isleme/">OpenCV ile webcam görüntüsü yakalama</a>yı bu yazımızda bir adım ileri götürerek görüntü işleme ile genelleştirilmiş olarak birleştireceğiz.</p>
<p><span id="more-158"></span></p>
<p>Görüntünün webcam üzerinden, bir avi dosyasından veya başka bir kaynaktan geliyor olması OpenCV kullandığımız için fark etmemektedir.</p>
<h2>Özetle OpenCV Görüntü Yakalama</h2>
<ol>
<li>OpenCV ile kamerayı açıyoruz.</li>
<li>İlk kareyi yakalıyoruz.</li>
<li>İlk kareyi hatasız yakaladıysak devam ediyoruz.</li>
<li>Kullanıcının &#8216;q&#8217; tuşuna basması ile çıkacağı bir döngüye giriyoruz.
<ol>
<li>Kareyi yakalıyoruz.</li>
<li>Kareyi istediğimiz boyuta getiriyoruz.(Örnekte 640 x 480)</li>
<li>Görüntü işleme metodumuzu çağırıyoruz.</li>
<li>Kareyi ekranda gösteriyoruz.</li>
</ol>
</li>
<li>Programdan çıkıyoruz.</li>
</ol>
<h2>Arayüzler, Sınıflar, Kalıtım ve dahası</h2>
<p>Burada geliştireceğimiz nokta, görüntü işlemenin <code>main.cpp</code> içerisindeki bir global metod olmaktan çıkarılmasıdır. Görüntü işleme için kullanabileceğimiz en basit arayüzü düşündüğümüzde, bu arayüzde görüntünün boyutları ve Filtrele metodundan başka bir içeriğe ihtiyaç olmadığını görüyoruz.</p>
<p>Bellek ile ilgili ayırma ve serbest bırakma özelliğinin de görüntü işleme sınıfında olması için <code>InitFilter</code> ve <code>ReleaseFilter</code> metodları kullanılmıştır.</p>
<p>Bu basit arabirimi aşağıdaki UML şemasında inceleyebiliriz.</p>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/05/ISingleImageFilter.png"><img class="aligncenter size-full wp-image-166" title="ISingleImageFilter Arayüzü" src="http://dissipatedHeat.com/wp-content/uploads/2011/05/ISingleImageFilter.png" alt="ISingleImageFilter Arayüzü" width="272" height="126" /></a></p>
<h3><code>main.cpp</code> dosyasında <code>ISingleImageFilter</code> Kullanımı</h3>
<ul>
<li>Filtreyi yaratmak,</li>
<li>InitFilter&#8217;ı looptan önce çağırmak,</li>
<li>ReleaseFilter&#8217;ı looptan çıkınca çağırmaktır.</li>
</ul>
<pre>
<pre class="brush: cpp; title: ; notranslate">
// ... OpenCV kamera açılır, kare yakalanır.

// Kullanacağımız filtre yaratılır.
ISingleImageFilter* myFilter = new IdentityFilter();

// Filtreye görüntünün boyutu bildirilir.
myFilter-&gt;InitFilter( 640, 480 );

// OpenCV görüntü yakalama döngüsü.
while( key != 'q' )
{
//	... kare yakalama.

	// Yakalanan görüntü işlenir.
	myFilter-&gt;FilterImage( imageData );

//	... kare gösterim.
}

// Filtre kaynaklarının serbest bırakılması istenir.
myFilter-&gt;ReleaseFilter();

// ... program çıkışı.
</pre>
</pre>
<h3><code>ISingleImageFilter</code> Kullanımı</h3>
<p><code>ISingleImageFilter</code>&#8216;da tüm filtrelerin kullanacağı en az iki değişken vardır. Görüntünün genişliği ve yüksekliği. Bu değişkenleri üye değişkenlerinde tutan ve tüm filtrelere ortak özellik eklenmesi gerektiğinde geliştirilebilecek bir sınıf olarak <code>SingleImageFilter</code> sınıfı yazılmıştır.</p>
<p><code>SingleImageFilter</code>, <code>ISingleImageFilter</code> sınıfından kalıtlanmıştır ve InitFilter metodu aşağıda verilmiştir.</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
	virtual void InitFilter(int width, int height)
	{
		this-&gt;width = width;
		this-&gt;height = height;
		this-&gt;isInited = true;
	}
</pre>
</pre>
<h3>En basit filtre: <code>IdentityFilter</code></h3>
<p><code>ISingleImageFilter</code> arayüzünün kullanımını en basit şekliyle göstermek amacıyla yazılmış bir filtre sınıfıdır. Kalıtladığı <code>SingleImageFilter</code> sınıfının <code>FilterImage</code> metodunu override eder.</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
class IdentityFilter : public SingleImageFilter
{
public:
	IdentityFilter()
	{
	}

	/** Görüntüde değişiklik yapmadan çıkar. */
	virtual void FilterImage(char* imageData)
	{
		return; // imajı değiştirmeden dön.
	}
};
</pre>
</pre>
<h3>CPU Üzerinde Negatif Görüntü Filtresi</h3>
<p>CPU üzerinde çalışan filtrelere örnek olarak negatif görüntü filtresi verilmiştir. Bu sınıfın sadece <code>FilterImage</code> metodu aşağıdadır.</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
	/** Görüntünün RGB kanallarının tersini alır. */
	virtual void FilterImage(char* imageData)
	{
		for(int i=0; i&lt;3*width*height; i++)
		{
			*( imageData + i ) = ( unsigned char ) ( 255 - *( imageData + i ) ); // her pikselin her kanalının negatifini al.
		}
	}
</pre>
</pre>
<p>Buraya kadarki filtrelerin UML şemasını gözden geçirecek olursak:</p>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/05/CPU-filters.png"><img class="aligncenter size-full wp-image-191" title="CPU filters" src="http://dissipatedHeat.com/wp-content/uploads/2011/05/CPU-filters.png" alt="CPU filters" width="609" height="540" /></a></p>
<h2>Yeniden Hoşgeldin CUDA!</h2>
<p>CUDA kodlarının çalışabilmesi için CUDA SDK 3.2 yazılımının bilgisayarınızda yüklü olması gerekmektedir. Kurulum için: <a href="http://dissipatedheat.com/2011/03/27/visual-studio-2010-ile-cuda-sdk-3-2-projesi-yaratmak/">VS2010 ile CUDA 3.2 Projesi Yaratmak</a></p>
<p>Görüntü işleme, CUDA kullanarak paralelleştirilmeye çok yatkın bir alandır. Her ne kadar bu yazıda anlatılan görüntü işleme metodları muazzam bir işlem gücü gerektirmese de metodların GPU&#8217;da CPU&#8217;dan daha hızlı çalıştığını farkedebilirsiniz.</p>
<p>CUDA üzerinde OpenCV&#8217;de yakaladığımız görüntüyü işleyebilmek için öncelikle bu görüntünün verisini ekran kartının belleğine yüklemeliyiz. Hesaplamayı GPU üzerinde yaptıktan sonra sonucu da CPU belleğine geri almalıyız.</p>
<h3><code>SingleCudaFilter::FilterImage</code> metodu</h3>
<ul>
<li>Kareyi yakala</li>
<li>SingleCudaFilter::FilterImage
<ul>
<li>Kareyi ekran kartı belleğine yükle</li>
<li>Filtreyi GPU üzerinde uygula</li>
<li>Sonucu CPU belleğine geri al</li>
</ul>
</li>
<li>Sonraki kareye geç</li>
</ul>
<p>Ekran kartı belleğinin ayrılması <code>InitFilter</code> metodunda, serbest bırakılması <code>ReleaseFilter</code> metodunda, verilerin ekran kartına kopyalanması ise <code>FilterImage</code> metodunda yapılır.</p>
<p>CUDA kullanmak için bir de kernele ihtiyacımız var. <code>SingleCudaFilter</code> sınıfında bu kernel parametrik olarak constructorda alınmaktadır. CUDA kernellerini derlemek için <strong>nvcc</strong> adlı nVidia derleyici sürücüsünün çalışması gerekmektedir ve bu kernellere olan referanslar MSVC derleyicisi tarafından algılanmamaktadır, dolayısıyla kernellerin metod işaretçilerini doğrudan kullanamıyoruz.</p>
<p>Kernelleri çağırmak için gereken griddeki blok ve bloktaki thread sayısını kullanarak kerneli çağıran metodlara proje kapsamında <strong>&#8220;kernel launcher&#8221;</strong> adı verilmiştir. Kernel launcherlar, aynı zamanda <code>ptKernelLauncher</code> tipindeki metod işaretçisi imzasını taşırlar.</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
/**
	Yaratıcıda alınan kerneli çağırır.

	\param imageData Görüntünün BGR kanal sıralı bellekteki adresi.

	Görüntüyü normalize ederek kernelLauncher işaretçisinin gösterdiği metodu çağırır ardından görüntüyü denormalize eder( [0, 255] aralığına ).
	Kernelde işlenen görüntüden sonuç olarak [0, 1] aralığı dışında bir değer dönerse o kanalın değeri [0, 255] aralığından dışarıda olabilir. Bu durumda değer yakın olduğu sınıra indirgenir.
*/
virtual void FilterImage(char* imageData)
{
	// imageData değişkenindeki görüntü verisi normalize edilerek h_Image değişkenine aktarılır.
	for(int i=0; i&lt;3*width*height; i++)
	{
		*(h_Image + i) = (unsigned char)*(imageData + i) / 255.0f; // normalize and copy image
	}

	/*
		Görüntü GPU belleğine kopyalanır.
	*/

	cudaMemcpy( d_Image, h_Image, 3 * sizeof(float) * width * height, cudaMemcpyHostToDevice );
	checkCUDAError(&quot;FilterImage: memcpy&quot;);

	/*
		Constructorda verilen kernel çalıştırılır.
	*/
	kernelLauncher( d_Image, width, height );

	/*
		Sonuçlar CPU belleğine kopyalanır.
	*/
	cudaMemcpy( h_Image, d_Image, 3 * sizeof(float) * width * height, cudaMemcpyDeviceToHost);
	checkCUDAError(&quot;FilterImage: memcpy2&quot;);

	/*
		h_Image değişkenindeki normalize edilmiş görüntü verisi [0, 255] aralığına çekilir.
	*/
	for(int i=0; i&lt;3*width*height; i++)
	{
		*(imageData + i) = satchar(*(h_Image + i) * 255);
	}
}
</pre>
</pre>
<p>Projedeki kernelleri çağırmak için kullanılan metod işaretçisi ve kullanımı:</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
typedef void (*ptKernelLauncher)(float*, int, int);

ptKernelLauncher kernelLauncher; // kernelLauncher değişkeni tanımlanır.

kernelLauncher = deviceInvertLaunch; // deviceInvertLaunch metodunun işaretçisi tanımlanan değişkene atanır.

kernelLauncher( d_Image, width, height ); // metod, işaretçisi üzerinden çağrılır. Çağrılan metod, GPU üzerinde çalışacak olan kerneli configuration parametreleri ile çağırır.
</pre>
</pre>
<p>Kerneli parametreleri ile çağırmak:</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
    dim3 dimBlock( BLOCK_SIZE, BLOCK_SIZE );
    dim3 dimGrid( height / dimBlock.x, width / dimBlock.y );

    gpuInvert&lt;&lt;&lt; dimGrid, dimBlock &gt;&gt;&gt;( d_Image, width, height);
</pre>
</pre>
<h2>Görüntü Negatifi &#8211; CUDA</h2>
<p>CUDA kerneli kullanarak görüntünün negatifini almak için kernelimizde görüntünün her bir pikselinin tersini almalıyız. Bu işlem için kernel aşağıdaki gibidir.</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
/**
	Görüntünün tersini alan kernel.

	\param image [0, 1] aralığına normalize edilmiş, BGR kanal sıralı görüntünün GPU belleğindeki adresi.
	\param width Görüntünün piksel olarak genişliği
	\param height Görüntünün piksel olarak yüksekliği

	Metod GPU üzerinde çalışır, çıktısını image parametresinin üzerine yazar.

	*/
__global__
void gpuInvert(
	float* image,
	int width,
	int height
	)
{
	int row = blockIdx.y * BLOCK_SIZE + threadIdx.y;
	int col = blockIdx.x * BLOCK_SIZE + threadIdx.x;

	int cIdx = ( row * width + col ) * 3; // 3 ile çarpım RGB için, linearIndex.

	// normalize edilmiş pikselleri 1'den çıkarttığımızda görüntünün negatifini almış oluruz.
	*( image + cIdx     ) = 1 - *( image + cIdx     ); // Blue kanalı
	*( image + cIdx + 1 ) = 1 - *( image + cIdx + 1 ); // Green kanalı
	*( image + cIdx + 2 ) = 1 - *( image + cIdx + 2 ); // Red kanalı
}
</pre>
</pre>
<p>Bu kernelin kullanımı iki şekildedir. Birincisi <code>SingleCudaFilter</code> sınıfını doğrudan <code>main.cpp</code> içinde kullanarak:</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
// deviceInvertLaunch kernel launcher metodu SingleCudaFilter sınıfına parametre olarak verilir.
ISingleImageFilter* myFilter = new SingleCudaFilter(deviceInvertLaunch);
</pre>
</pre>
<p>İkincisi ise bu parametreyi kendi constructorında <code>SingleCudaFilter</code> sınıfının constructoruna veren bir sınıf yazmaktır. Tek bir filtre için tek bir sınıf yazmanın getirisi, hangi kernelin kullanılacağını bilmeye gerek olmamasıdır, <code>ptKernelLauncher</code>, sınıfın içinde bir kere yazılır.</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
/**
	CUDA kullanarak GPU üzerinde görüntünün negatifini alan filtre sınıfı.
*/
class CudaInvertFilter : public SingleCudaFilter
{
public:
	/**
		\ref deviceInvertLaunch metod işaretçisi parametresi ile SingleCudaFilter yaratıcısını çağırır.
	*/
	CudaInvertFilter()
		: SingleCudaFilter(deviceInvertLaunch)
	{
	}
};
</pre>
</pre>
<h2>Texturelar</h2>
<p>Buraya kadar bahsedilen CUDA filtreleri, tamamen ekran kartı global belleği üzerinden çalışmaktadır. Okumalar <strong>texture</strong> belleğinden yapılarak zaman kazanılabilir ve texture önbelleğinden otomatik olarak faydalanılabilir. Texture önbelleği, erişimde yerellik olduğu zaman örneğin bir piksele eriştiğinizden hemen ardından o pikselin 2 boyutlu düzlemdeki komşularına eriştiğinizde devreye girerek bellek okuma işlemlerinin bir miktar hızlanmasını sağlayabilir.</p>
<p>Textureları CUDA ile kullanabilmek için <code>cuArray</code> tipinde tanımlanan değişken üzerinden işlemler yürütülür. Texture üzerine hiçbir zaman doğrudan veri kopyalanmaz çünkü texturelar salt-okunurdur. Bir CUDA textureına <code>cuArray</code> atanarak yazma işlemleri <code>cuArray</code>&#8216;e yapıldığında, texture otomatik olarak yazılan veriyi üzerine alacaktır.</p>
<p>Texturelar ile ilgili karşılaşılan sorun, kullanılacak textureın, <strong>kernelin bulunduğu</strong> .cu dosyasında olması zorunluluğudur. Ortak bir başlık dosyasında texture tanımlanıp hem kernelin bulunduğu dosyadan, hem de bu textureı yönetmek istediğimiz sınıfın dosyasından içerildiğinde, texturelar nvcc tarafından farklı olarak algılanmaktadır.</p>
<p>Texture değişkeninin scopeu:</p>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/05/texture-degiskeninin-scopeu.png"><img src="http://dissipatedHeat.com/wp-content/uploads/2011/05/texture-degiskeninin-scopeu.png" alt="texture degiskeninin scopeu" title="texture degiskeninin scopeu" width="600" height="210" class="aligncenter size-medium wp-image-205" /></a></p>
<p>Kernelin bulunduğu dosya dışındaki bir sınıftan texturea veri yüklemesi ve diğer texture ayarlarının yapılması için nVidia&#8217;nın CUDA Driver API&#8217;si kullanılabilir. Adı sizi korkutmasın, tek satırda yapılan işlemi başka bir dosyadan yapmak istediğimizde bir kaç satırda yapıyoruz, tek fark bu.</p>
<p><code>SingleCudaTexFilter</code> sınıfında texture yönetimi ile ilgili bir diğer ince nokta da CUDA kodlarında <code>cudaGetTextureReference</code> ve benzeri metodların parametre olarak <code>const</code> bir referans beklemesidir. Bizim niyetimiz textureı değiştirmek olduğundan CUDA Driver API&#8217;si ile anlaşabilmek için ara bir değişken kullanıyoruz.</p>
<p><code>cuda_runtime_api.h</code> içinde <code>cudaGetTextureReference</code> tanımı:</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
extern __host__ cudaError_t CUDARTAPI cudaGetTextureReference(const struct textureReference **texref, const char *symbol);
</pre>
</pre>
<p><code>SingleCudaTexFilter</code> içerisinde textureın <code>const</code>&#8216;unun kaldırılarak ara değişkene atanması ve kullanımı:</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
	const textureReference* constTexRefPtr;
	textureReference* texRefPtr;

	...

	// cudaGetTextureReference, istediği gibi const texture referansı ile çağrılır.
	cudaGetTextureReference(&amp;constTexRefPtr, textureSymbolName);
	checkCUDAError(&quot;get texture reference&quot;);

	// const olan referans, const olmayan referansa dönüştürülerek saklanır.
	texRefPtr = const_cast&lt;textureReference*&gt;( constTexRefPtr );
	channelDesc = cudaCreateChannelDesc&lt;float4&gt;();

	// const olmayan texture referansının kullanımı.
	cudaMallocArray( &amp;cu_array, &amp;texRefPtr-&gt;channelDesc, width, height );
	checkCUDAError(&quot;malloc device image&quot;);

	...

	// cu_array üzerine kopyalanan veriler texture atanacak.
	cudaMemcpyToArray( cu_array, 0, 0, h_Image, sizeof(float4) * width * height, cudaMemcpyHostToDevice);
	checkCUDAError(&quot;FilterImage: memcpy&quot;);

	// cu_array, texturea atanır.
	cudaBindTextureToArray( texRefPtr, cu_array, &amp;texRefPtr-&gt;channelDesc );
</pre>
</pre>
<p>Texture kullanımı ile ilgili olarak <code>SingleCudaTexFilter.cu</code> ve <code>SingleCudaTexFilter.h</code> dosyalarını <a href="http://dissipatedheat.com/doxygen/imageFilterLib/files.html">inceleyebilirsiniz</a>.</p>
<h2>Görüntü Negatifi &#8211; CUDA Texture</h2>
<p>CUDA ile texture belleğini kullanarak görüntünün negatifini almak için kernelimizde görüntünün her bir pikselini textureın her bir pikselinin tersinden oluşturmalıyız. Bu işlem için kernel aşağıdaki gibidir.</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
/**
	Texture kullanarak görüntünün negatifini alan kernel.

	\param image [0, 1] aralığına normalize edilmiş, BGR kanal sıralı görüntünün GPU belleğindeki adresi.
	\param width Görüntünün piksel olarak genişliği
	\param height Görüntünün piksel olarak yüksekliği

	Metod GPU üzerinde çalışır, çıktısını image parametresinin üzerine yazar.
*/
__global__
void gpuTexInvert(
	float* image,
	int width,
	int height
	)
{
	int row = blockIdx.y * BLOCK_SIZE + threadIdx.y;
	int col = blockIdx.x * BLOCK_SIZE + threadIdx.x;

	int cIdx = ( row * width + col ) * 3; // 3 ile çarpım RGB için, linearIndex.

	// threade ait kordinatın texture uzayındaki kordinatı bulunur.
	float tu = (float)col / width;
	float tv = (float)row / height;

	// Texture üzerinden görüntü verisi okunur.
	float4 texVal = tex2D( texInvert1, tu, tv );

	// Texture değerleri 1'den çıkartılarak global belleğe yazılır.
	*( image + cIdx )     = 1 - texVal.x;
	*( image + cIdx + 1 ) = 1 - texVal.y;
	*( image + cIdx + 2 ) = 1 - texVal.z;
}
</pre>
</pre>
<p>Texture kullanan kernel de texture kullanmayan CUDA negatif kerneli gibi iki şekilde kullanılabilir. Detaylar için kaynak kodu <a href="http://dissipatedheat.com/doxygen/imageFilterLib/files.html">inceleyebilirsiniz</a>.</p>
<h2>Filtre Zinciri: <code>SingleImageFilterChain</code></h2>
<p>Filtre zinciri, birbiri ardına uygulanacak filtreleri barındıran bir sınıftır. Bu sınıf <code>SingleImageFilter</code> sınıfından kalıtlanmıştır. <code>AppendFilter</code> metodu ile sınıfa işlemesi için filtreleri sıralı olarak verebilirsiniz. <code>FilterImage</code> metodu çağrıldığında zincirdeki tüm filtreler için <code>FilterImage</code> metodu çağrılacaktır.</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
ISingleImageFilter* myFilter1 = new SingleCudaTexFilter(deviceTexAbsDiffLaunch, &quot;texAbsDiff1&quot;);
ISingleImageFilter* myFilter2 = new CpuInvertFilter();

SingleImageFilterChain* myFilter = new SingleImageFilterChain();
myFilter-&gt;AppendFilter( myFilter1 );
myFilter-&gt;AppendFilter( myFilter2 );

// myFilter'a atanmış olan filtre zinciri, ISingleImageFilter arayüzünü gerçeklediği için diğer filtreler gibi kullanılabilir.
</pre>
</pre>
<h2>UML Şeması</h2>
<p>UML Şeması basitleştirilmiş olarak verilmiştir:</p>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/05/HelloOpenCV.png"><img class="aligncenter size-large wp-image-219" title="UML Şeması" src="http://dissipatedHeat.com/wp-content/uploads/2011/05/HelloOpenCV-831x1024.png" alt="UML Şeması" width="640" height="788" /></a></p>
<h2>Filtre Örnekleri</h2>
<p><code>IdentityFilter</code>:<br />
<a href="http://dissipatedHeat.com/wp-content/uploads/2011/05/identity-filter.png"><img class="aligncenter size-full wp-image-222" title="IdentityFilter" src="http://dissipatedHeat.com/wp-content/uploads/2011/05/identity-filter.png" alt="IdentityFilter" width="641" height="481" /></a></p>
<p><code>CudaSepiaFilter</code>:<br />
<a href="http://dissipatedHeat.com/wp-content/uploads/2011/05/sepia-filter.png"><img class="aligncenter size-full wp-image-225" title="CudaSepiaFilter" src="http://dissipatedHeat.com/wp-content/uploads/2011/05/sepia-filter.png" alt="CudaSepiaFilter" width="642" height="480" /></a></p>
<p><code>CudaTexBoxBlurFilter</code>:<br />
<a href="http://dissipatedHeat.com/wp-content/uploads/2011/05/box-blur.png"><img class="aligncenter size-full wp-image-226" title="CudaTexBoxBlurFilter" src="http://dissipatedHeat.com/wp-content/uploads/2011/05/box-blur.png" alt="CudaTexBoxBlurFilter" width="642" height="480" /></a></p>
<p><code>SingleImageFilterChain</code>: <code>deviceTexAbsDiffLaunch</code> kerneli ardından <code>CpuInvertFilter</code>:<br />
<a href="http://dissipatedHeat.com/wp-content/uploads/2011/05/abs-diff-ve-invert.png"><img class="aligncenter size-full wp-image-227" title="SingleImageFilterChain" src="http://dissipatedHeat.com/wp-content/uploads/2011/05/abs-diff-ve-invert.png" alt="SingleImageFilterChain" width="609" height="479" /></a></p>
<h3><a style="text-decoration: none;" name="indirmeler">İndirmeler</a></h3>
<p><strong>Dosyalar <a href="http://www.7-zip.org">7-zip</a> ile sıkıştırılmıştır.</strong></p>
<ul>
<li>Proje Kodları: <a href="http://dissipatedHeat.com/wp-content/uploads/2011/05/ImageFilterLib-HelloOpenCV.7z">ImageFilterLib &#8211; HelloOpenCV</a></li>
<li><a href="http://dissipatedheat.com/doxygen/imageFilterLib/inherits.html">Doxygen Belgeleri Mikrositesi</a></li>
</ul>
<p>NOT: Kerneller optimize edilmemiştir.</p>
<img src="http://feeds.feedburner.com/~r/dheat/~4/r0Xmkhr_Ec4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://dissipatedHeat.com/2011/05/29/cuda-ile-opencv-kullanarak-webcam-goruntu-isleme/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://dissipatedHeat.com/2011/05/29/cuda-ile-opencv-kullanarak-webcam-goruntu-isleme/</feedburner:origLink></item>
		<item>
		<title>OpenCV ile Webcam Görüntüsü İşleme</title>
		<link>http://feedproxy.google.com/~r/dheat/~3/3ZDE2Nm7hhw/</link>
		<comments>http://dissipatedHeat.com/2011/04/24/opencv-ile-webcam-goruntusu-isleme/#comments</comments>
		<pubDate>Sun, 24 Apr 2011 18:15:17 +0000</pubDate>
		<dc:creator>Kerem Kat</dc:creator>
				<category><![CDATA[OpenCV]]></category>
		<category><![CDATA[capture]]></category>
		<category><![CDATA[vs2010]]></category>
		<category><![CDATA[webcam]]></category>

		<guid isPermaLink="false">http://dissipatedHeat.com/?p=127</guid>
		<description><![CDATA[OpenCV Nedir? OpenCV, açık kaynaklı bir bilgisayarlı görselleştirme kütüphanesidir. Amacı görüntü işleme ve görselleştirmede sık kullanılan metodların kolaylıkla erişilebilir olmasını sağlamaktadır. Yazımızda kullandığımız OpenCV 2.2 ile webcam görüntüsü işlerken bu kolaylığı farkedeceğiz. Webcam görüntüsünü alacağım derseniz bir yolu da DirectShow kullanmaktır ki bu yol uzun ince bir yoldur, bkz. DirectShow Webcam Webcam Görüntüsünü Almak Yüklü <a href='http://dissipatedHeat.com/2011/04/24/opencv-ile-webcam-goruntusu-isleme/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<h2>OpenCV Nedir?</h2>
<p>OpenCV, açık kaynaklı bir bilgisayarlı görselleştirme kütüphanesidir. Amacı görüntü işleme ve görselleştirmede sık kullanılan metodların kolaylıkla erişilebilir olmasını sağlamaktadır. Yazımızda kullandığımız OpenCV 2.2 ile webcam görüntüsü işlerken bu kolaylığı farkedeceğiz.</p>
<p>Webcam görüntüsünü alacağım derseniz bir yolu da DirectShow kullanmaktır ki bu yol uzun ince bir yoldur, bkz. <a href="http://www.codeproject.com/KB/audio-video/WebcamUsingDirectShowNET.aspx">DirectShow Webcam</a></p>
<h2>Webcam Görüntüsünü Almak</h2>
<p>Yüklü ve windows tarafından tanınmış olan webcaminizden OpenCV kullanarak görüntü almak için yazmanız gereken kod sadece tek bir satırdır.<br />
<span id="more-127"></span></p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
	CvCapture* capture = 0;
	capture = cvCaptureFromCAM(0);
	IplImage* videoFrame = NULL;

	videoFrame = cvQueryFrame(capture); // kameradan görüntü alınır
</pre>
</pre>
<h2>Gerekenler</h2>
<ul>
<li> VS 2010 ve C/C++ Bilgisi</li>
<li> <a href="http://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.2/OpenCV-2.2.0-win32-vs2010.exe/download">OpenCV 2.2 Kurulumu</a></li>
<li>OpenCV&#8217;yi kendiniz patchlemek isterseniz:
<ul>
<li><a href="http://www.cmake.org/files/v2.8/cmake-2.8.4-win32-x86.exe">CMake</a>, OpenCV&#8217;yi patchledikten sonra build etmek için.</li>
<li>OpenCV 2.2 Windows webcam patchi: <a href="http://blog.qinyujie.net/2011/01/15/440/">İngilizce</a></li>
</ul>
</li>
<li>Patchli dll ve libleri indirmek isterseniz:
<ul>
<li><a href="#indirmeler">İndirmeler</a></li>
</ul>
</li>
</ul>
<h2>İzlenen Yol</h2>
<h3>OpenCV 2.2 Patch</h3>
<p>OpenCV 2.2 sürümünde mevcut olan bir bug, windows makinalarda görüntü alınmasına engel olmaktadır. Bu bugın varlığını keşfedinceye kadar bilgisayarımdan ve kameramdan şüphe etmiştim, neyseki şüphelerim yersizmiş. Patch deyince gözünüz korkmasın, sadece tek bir dosyada iki satır değişiklik yapmak gerekiyor. Bu satırlar için bkz. <a href="http://blog.qinyujie.net/2011/01/15/440/">OpenCV 2.2 patch</a>.</p>
<p>Yok ben dosyalarımı patchli kullanırım derseniz <a href="#indirmeler">İndirmeler</a> bölümünden OpenCV patch dosyasını indirip içindeki dll dosyalarını c:\opencv2.2\bin içerisinde, lib dosyalarını da c.\opencv2.2\lib dizinine oradaki dosyaların üzerine yazarak kopyalayabilirsiniz.</p>
<h3>Visual Studio Projesi</h3>
<ul>
<li>Empty Win32 Console Project yaratarak yolculuğumuza başlıyoruz.</li>
<li>Projemizin özellik sayfasında VC++ Directories&#8217;de includeları ekliyoruz:
<pre>C:\OpenCV2.2\include</pre>
</li>
<li>Projemizin özellik sayfasında VC++ Directories&#8217;de libraryleri ekliyoruz:
<pre>C:\OpenCV2.2\lib</pre>
</li>
<li>Kullanacağımız kütüphane dosyalarını Linker-&gt;Input-&gt;Additional Dependencies&#8217;e ekliyoruz.
<pre>opencv_core220.lib
opencv_highgui220.lib
opencv_imgproc220.lib</pre>
</li>
<li>Yaratacağımız main.h dosyasına içeriği ekliyoruz:
<pre>
<pre class="brush: cpp; title: ; notranslate">
#pragma once // Header dosyasına birden fazla referans olsa bile sadece 1 kere işlensin.

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

#include &quot;opencv2\opencv.hpp&quot;
</pre>
</pre>
</li>
<li>Yaratacağımız main.cpp dosyasına webcamden capture edip görüntüyü negatif yaparak ekranda göstermeye yarayacak aşağıdaki kodu ekliyoruz.
<pre>
<pre class="brush: cpp; title: ; notranslate">

#include &quot;main.h&quot; // tüm başlıklarımızı ve tanımlamalarımızı içeren başlık dosyası.

int main( int argc, char** argv )
{
	int key = -1;

	CvCapture* capture = 0;

	// İlk tanımlı kameranın tutacağını al. (tutacak = handle).
	capture = cvCaptureFromCAM( 0 );
	if( !capture )
	{
		// Tutacak geçersiz ise programdan çık.
		fprintf( stderr, &quot;Kamera tutacağı edinilemedi...\n&quot; ); // bilgilendiiir.
		exit( EXIT_FAILURE );
	}

	// Görüntü için pointer.
	IplImage* videoFrame = NULL; 

	// ilk kareyi yakala.
	videoFrame = cvQueryFrame( capture ); 

	if( !videoFrame )
	{
		// Kare yakalanamadı, programdan çık.
		printf( &quot;Kare yakalanamadı...\n&quot; );
		exit( EXIT_FAILURE );
	}

	// MainVideo adında bir gösterim penceresi yarat.
	cvNamedWindow( &quot;MainVideo&quot;, 1 );

	// q tuşuna basana kadar dön.
	while( key != 'q' )
	{
		// Bir kare al.
		videoFrame = cvQueryFrame( capture );

		// Kare geçersiz ise loop biter.
		if( !videoFrame )
			break;

		// Karenin tüm pixellerini ters çevir, negatif resim efekti.
		// Not: Görüntü tipinin BGR olduğu varsayılmıştır. Normalde kontrol edilmelidir.
		for( int i=0; i &lt; videoFrame-&gt;imageSize; i++ )
		{
			videoFrame-&gt;imageData[i] = 255 - videoFrame-&gt;imageData[i];
		}

		// Negatif görüntüyü pencerede göster.
		cvShowImage( &quot;MainVideo&quot;, videoFrame );

		key = cvWaitKey( 10 ); // 10ms tuş için bekle.
	}

	cvDestroyAllWindows(); // yarattığımız pencereyi yokeder.

	cvReleaseCapture( &amp;amp;amp;amp;amp;amp;amp;amp;capture ); // Kameranın tutacağını bırakır.

	exit( EXIT_SUCCESS );
}
</pre>
</pre>
</li>
</ul>
<h3>Gerçek Zamanlı Webcam Negatifi</h3>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/04/negatif1.png"><img class="aligncenter size-full wp-image-136" title="negatif1" src="http://dissipatedHeat.com/wp-content/uploads/2011/04/negatif1.png" alt="" width="770" height="591" /></a></p>
<h3><a style="text-decoration: none;" name="indirmeler"> İndirmeler<br />
</a></h3>
<p><strong>Dosyaları açabilmek için farklı kaydederek uzantısını <a href="http://www.7-zip.org">7z</a> yapınız.</strong><br />
Patchlenmiş OpenCV dosyaları: <a href="http://dissipatedHeat.com/wp-content/uploads/2011/04/OpenCV2.2-webcam-patch.txt">OpenCV2.2 webcam patch</a><br />
Örnek Proje Kaynakları: <a href="http://dissipatedHeat.com/wp-content/uploads/2011/04/HelloOpenCV.txt">HelloOpenCV</a></p>
<img src="http://feeds.feedburner.com/~r/dheat/~4/3ZDE2Nm7hhw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://dissipatedHeat.com/2011/04/24/opencv-ile-webcam-goruntusu-isleme/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://dissipatedHeat.com/2011/04/24/opencv-ile-webcam-goruntusu-isleme/</feedburner:origLink></item>
		<item>
		<title>CUDA ile Matris Çarpımı – 2</title>
		<link>http://feedproxy.google.com/~r/dheat/~3/RcnKX-qeAZY/</link>
		<comments>http://dissipatedHeat.com/2011/04/24/cuda-ile-matris-carpimi-2/#comments</comments>
		<pubDate>Sun, 24 Apr 2011 16:49:15 +0000</pubDate>
		<dc:creator>Kerem Kat</dc:creator>
				<category><![CDATA[CUDA]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[nVidia]]></category>
		<category><![CDATA[parallel]]></category>
		<category><![CDATA[visual studio 2010]]></category>
		<category><![CDATA[vs]]></category>
		<category><![CDATA[vs2010]]></category>

		<guid isPermaLink="false">http://dissipatedHeat.com/?p=106</guid>
		<description><![CDATA[Matris Çarpımı CUDA &#8211; 2 Bir önceki yazımızda CUDA ile matris çarpımının nasıl yapılabileceğini en basit hali ile görmüştük. Burada geçen sefer kaldığımız yer olan hafıza erişim optimizasyonuna devam ediyoruz. En son matMul2 isimli kernel içerisinde toplam alınan satırda hafızaya yapılan yazmaları azaltmıştık. Paylaşık Hafıza (Shared Memory) Paylaşılmış olmayan hafıza mı vardır dediğinizi duyar gibiyim. <a href='http://dissipatedHeat.com/2011/04/24/cuda-ile-matris-carpimi-2/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<h2>Matris Çarpımı CUDA &#8211; 2</h2>
<div><a href="http://dissipatedheat.com/2011/04/10/cuda-ile-matris-carpimi-1/">Bir önceki yazımızda</a> CUDA ile matris çarpımının nasıl yapılabileceğini en basit hali ile görmüştük. Burada geçen sefer kaldığımız yer olan hafıza erişim optimizasyonuna devam ediyoruz.</div>
<div>En son matMul2 isimli kernel içerisinde toplam alınan satırda hafızaya yapılan yazmaları azaltmıştık.</div>
<p><span id="more-106"></span></p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
matMul1 (n adet global store):

d_C[ cIdx ] = 0;

// C matrisinin her bir hücresi için
for(int j=0; j&lt;n; j++)
{
	// her bir eleman için C matrisinin bir elemanı okunur ve yazılır.
	d_C[ cIdx ] += *loc( d_A, n, i, j ) * *loc( d_B, r, j, k ); // global hafızaya yazılır(d_C).
}
</pre>
</pre>
<pre>
<pre class="brush: cpp; title: ; notranslate">
matMul2 (1 adet global store):

float val = 0; // ara toplam değişkeni

// C matrisinin her bir hücresi için
for(int j=0; j&lt;n; j++)
{
	val += *loc( d_A, n, i, j ) * *loc( d_B, r, j, k ); // local registera(val) yazılır.
}

// C matrisine bir kere yazılır.
d_C[ cIdx ] = val;
</pre>
</pre>
<h2>Paylaşık Hafıza (Shared Memory)</h2>
<p>Paylaşılmış olmayan hafıza mı vardır dediğinizi duyar gibiyim. Global Hafıza da paylaşılmıştır elbet, herkes yazabilir herkes okuyabilir. Fakat burada bir nVidia terimi olarak geçen &#8220;paylaşık hafıza&#8221; bir blok içerisindeki threadler arasında paylaşılmıştır. Yani ancak aynı blok içerisindeki threadler aynı yeri okuyabilir ve aynı yere yazabilir.</p>
<p>Bir bloktaki threadler paylaşık hafızaya yardımlaşarak yükledikleri verileri kullanabilirler.</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
...

Ais[threadIdx.y][threadIdx.x] = *loc( d_A, n, i, j ); // A(i,j) elemanı Ais paylaşık hafızasına yüklenir.
Bis[threadIdx.y][threadIdx.x] = *loc( d_A, n, j, k ); // A(j,k) elemanı Bis paylaşık hafızasına yüklenir.

// kullanılacak elemanlar paylaşık hafızaya yüklenir.
__syncthreads(); // syncthreads, bloktaki tüm threadlerin bu noktaya erişmesini bekletir.

for(int k=0; k&lt;BLOCK_SIZE;k++)
{
	val += Ais[threadIdx.y][k] * Bis[k][threadIdx.x];
}

// tüm threadlerin sonucu yazması beklenir.
__syncthreads(); // syncthreads, bloktaki tüm threadlerin bu noktaya erişmesini bekletir.
</pre>
</pre>
<h2>2. Optimizasyon (Paylaşık Hafıza)</h2>
<p>Yapılan optimizasyonda paylaşık hafıza kullanılarak global hafızadan okuma sayısı düşürülmüştür.</p>
<pre>
<pre class="brush: cpp; title: ; notranslate">
__global__
void matMul3(
	float* d_C,
	float* d_A,
	float* d_B,
	int m,
	int n,
	int r)
{

	__shared__ float Ais[BLOCK_SIZE][BLOCK_SIZE];
	__shared__ float Bis[BLOCK_SIZE][BLOCK_SIZE];

	int i = blockIdx.x * BLOCK_SIZE + threadIdx.x;
	int k = blockIdx.y * BLOCK_SIZE + threadIdx.y;

	int cIdx = i*m + k;

	float val = 0; // ara toplam değişkeni

	for(int j=0; j &lt; n / BLOCK_SIZE; j++)
	{
		Ais[threadIdx.y][threadIdx.x] = *loc( d_A, n, i, j );
		Bis[threadIdx.y][threadIdx.x] = *loc( d_B, n, j, k );

		// kullanılacak elemanlar paylaşık hafızaya yüklenir.
		__syncthreads();

		for(int k=0; k&lt;BLOCK_SIZE;k++)
		{
			val += Ais[threadIdx.y][k] * Bis[k][threadIdx.x];
		}

		// tüm threadlerin sonucu yazması beklenir.
		__syncthreads();
	}

	// C matrisine bir kere yazılır.
	d_C[ cIdx ] = val;
}
</pre>
</pre>
<h2>Zamanlama</h2>
<p>512 x 512 boyutlarında iki matrisin çarpım sürelerini karşılaştırabiliriz.</p>
<table>
<tbody>
<tr>
<td>Versiyon</td>
<td>Hız (ms)</td>
<td>Hızlanma</td>
</tr>
<tr>
<td>Host</td>
<td>9619</td>
<td>1x</td>
</tr>
<tr>
<td>MatMul1</td>
<td>509</td>
<td>19x</td>
</tr>
<tr>
<td>MatMul2</td>
<td>183</td>
<td>53x</td>
</tr>
<tr>
<td>MatMul3</td>
<td>72</td>
<td>135x</td>
</tr>
</tbody>
</table>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/04/512x512-matmul-results.png"><img class="aligncenter size-full wp-image-114" title="512x512 matmul results" src="http://dissipatedHeat.com/wp-content/uploads/2011/04/512x512-matmul-results.png" alt="" width="351" height="149" /></a></p>
<h2>Referanslar</h2>
<ul>
<li><a href="http://www.elsevierdirect.com/morgan_kaufmann/kirk/">Programming Massively Parallel Processors</a></li>
</ul>
<p><strong>Proje dosyasını açabilmek için farklı kaydederek uzantısını <a href="http://www.7-zip.org">7z</a> yapınız.</strong><br />
Kaynakları indir: <a href="http://dissipatedHeat.com/wp-content/uploads/2011/04/CUDA-MatMul3.txt">CUDA matris carpimi 2</a></p>
<img src="http://feeds.feedburner.com/~r/dheat/~4/RcnKX-qeAZY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://dissipatedHeat.com/2011/04/24/cuda-ile-matris-carpimi-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://dissipatedHeat.com/2011/04/24/cuda-ile-matris-carpimi-2/</feedburner:origLink></item>
		<item>
		<title>CUDA ile Matris Çarpımı – 1</title>
		<link>http://feedproxy.google.com/~r/dheat/~3/kSGaVT1qxbg/</link>
		<comments>http://dissipatedHeat.com/2011/04/10/cuda-ile-matris-carpimi-1/#comments</comments>
		<pubDate>Sun, 10 Apr 2011 20:02:20 +0000</pubDate>
		<dc:creator>Kerem Kat</dc:creator>
				<category><![CDATA[CUDA]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[nVidia]]></category>
		<category><![CDATA[parallel]]></category>
		<category><![CDATA[visual studio 2010]]></category>
		<category><![CDATA[vs]]></category>
		<category><![CDATA[vs2010]]></category>

		<guid isPermaLink="false">http://dissipatedHeat.com/?p=86</guid>
		<description><![CDATA[Matris Çarpımı CUDA Matrislere iki boyutlu vektörler dersek vektörleri tek boyutlu değişkenler gibi görmek, değişkenlere de &#8220;boyutsuz&#8221; benzetmesini yapmak yerinde olacaktır. Matris nedir sorusunun cevabını aramayacağımız bu yazımızda matris çarpımını C dilinde CPU üzerinde ve GPU üzerinde en basit haliyle nasıl yapabileceğimizi göreceğiz. Örnek kodlarda kodun basitliği açısından kare matrisler kullanılmıştır. A: M x N <a href='http://dissipatedHeat.com/2011/04/10/cuda-ile-matris-carpimi-1/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<h2>Matris Çarpımı CUDA</h2>
<div>Matrislere iki boyutlu vektörler dersek vektörleri tek boyutlu değişkenler gibi görmek, değişkenlere de &#8220;boyutsuz&#8221; benzetmesini yapmak yerinde olacaktır. <a href="http://en.wikipedia.org/wiki/The_Matrix">Matris</a> nedir sorusunun cevabını aramayacağımız bu yazımızda matris çarpımını C dilinde CPU üzerinde ve GPU üzerinde en basit haliyle nasıl yapabileceğimizi göreceğiz.</div>
<div>Örnek kodlarda kodun basitliği açısından kare matrisler kullanılmıştır.</div>
<p><span id="more-86"></span></p>
<div><code>A: M x N</code> ( M satır, N sütun),<br />
<code>B: N x R</code><br />
<code>C: M x R</code> boyutlarında seçilmiştir.</div>
<div>Örnek kodlarda matrislerin boyutları #define ile tanımlanacaktır fakat bu yazımızdaki örneklerde <code>M = N = R</code> olarak seçilmelidir.</div>
<div>
<h3>Tanımlar:</h3>
</div>
<div><img style="background-color: white;" src="http://www.codecogs.com/eq.latex?A_{i,j}" alt="A_{i,j}" /> A matrisinin i. satırının j. sütunundaki eleman<br />
<img style="background-color: white;" src="http://www.codecogs.com/eq.latex?C = AB" alt="C = AB" /><br />
<img style="background-color: white;" src="http://www.codecogs.com/eq.latex?C_{i,k}=\sum^N_{j=1}A_{i,j} B_{j,k}" alt="C_{i,k}=\sum^N_{j=1}A_{i,j} B_{j,k}" /><br />
Bu yazımızdaki örnekler:</div>
<ul>
<li>C ile yazılmış naif matris çarpımı</li>
<li>Optimize edilmemiş GPU kerneli</li>
<li>1. Optimizasyon</li>
</ul>
<div>Optimizasyon çok basit olarak yapılmıştır öyleki optimizasyon demeye dilim varmıyor. İleriki yazılarda kernel adım adım optimize edilerek GPU&#8217;nun suyu sıkılacaktır.</div>
<h2>Naif CPU Matris Çarpımı</h2>
<div>C matrisinin her elemanı için A matrisinin N sütunu ve B matrisinin N satırı çarpılarak toplanır. <code>M x N x R</code> kere loop döner ( O(n^3), n kare matrisimizin bir boyutu )<br />
Bu algoritma, matris çarpımının &#8220;text-book&#8221; çözümüdür.</div>
<pre>
<pre class="brush: cpp; title: ; notranslate">
inline
float* h_loc(float* h_B, int width, int i, int j)
{
	return h_B + i*width + j;
}

void hostMatrixMultiply(
	float* h_C,
	float* h_A,
	float* h_B,
	int m,
	int n,
	int r)
{

	clock_t start = clock(), diff;

	for(int i=0; i&lt;m; i++)
	{
		for(int k=0; k&lt;r; k++)
		{
			float sum = 0;
			for(int j=0; j&lt;n; j++)
			{
				sum += *h_loc(h_A, n, i, j) * *h_loc(h_B, r, j, k);
			}

			*h_loc(h_C, r, i, k) = sum;
		}
	}

	diff = clock() - start;

	int msec = diff * 1000 / CLOCKS_PER_SEC;
	printf(&quot;hostMatrixMultiply: %i ms\n&quot;, msec);

}
</pre>
</pre>
<h2>Optimize Edilmemiş GPU Kerneli</h2>
<div>deviceMultiply1 fonksiyonunun çağırdığı matMul1 kerneli, performans hakkında en ufak tedirginlik hissedilmeden yazılmış bir matris çarpım kernelidir. deviceMultiply1 girizgah fonksiyonunda GPU üzerinde hafıza ayrılmakta, matrisler GPU hafızasına kopyalanmakta ve hesaplanan sonuç CPU hafızasına alındıktan sonra GPU üzerinde ayrılan hafızalar bırakılmaktadır. Sonucun hesaplanması matMul1 kernelinde gerçekleşir.</div>
<div>deviceMultiply1 fonksiyonunda matMul1 kerneli çağrılmadan önce grid ve block boyutları hesaplanır. GPU üzerinde çalışacak thread sayısının C matrisindeki eleman sayısı kadar olmasını sağlayacak değerler hesaplanır. Daha sonra</p>
<pre class="brush: cpp; title: ; notranslate">matMul1&lt;&lt;&lt; dimGrid, dimBlock &gt;&gt;&gt;( d_C, d_A, d_B, m, n, r);</pre>
<p>satırıyla kernel çağrılır.</p></div>
<div>Memory access sayısının düşürülmesi, memory coalescing, tiling gibi hiçbir teknik kullanılmadan yazılmış olan naif CUDA matris çarpım kernelini birlikte inceleyelim.</div>
<pre>
<pre class="brush: cpp; title: ; notranslate">
__global__
void matMul1(
	float* d_C,
	float* d_A,
	float* d_B,
	int m,
	int n,
	int r)
{
	int i = blockIdx.x * BLOCK_SIZE + threadIdx.x; // GPU threadinin hesaplayacağı C matrisinin satırı.
	int k = blockIdx.y * BLOCK_SIZE + threadIdx.y; // GPU threadinin hesaplayacağı C matrisinin sütunu

	int cIdx = i*m + k; // Hesaplanacak elemanın C indisi.

	d_C[ cIdx ] = 0;

	// C matrisinin her bir hücresi için
	for(int j=0; j&lt;n; j++)
	{
		// her bir eleman için C matrisinin bir elemanı okunur ve yazılır.
		d_C[ cIdx ] += *loc( d_A, n, i, j ) * *loc( d_B, r, j, k );
	}
}</pre>
</pre>
<h2>1. Optimizasyon (Hafıza Erişimi)</h2>
<div>matMul1 kernelinde yapılacak çok ufak bir değişiklik ile performans arttırılabilir. Bu değişikliğin getirdiği hız kazancı, GPU&#8217;da hafıza erişim işlemlerinin CPU hafızasına erişimden çok daha yavaş olması ile gün ışığına çıkmaktadır.</div>
<div>matMul1 kernelinde d_C, C matrisinin GPU hafızasındaki yerine işaretçidir(pointer). Bu işaretçinin kullanıldığı her yer GPU hafızasına erişmek demektir. İşaretçi başta sıfırlanmıştır ve toplama işlemi işaretçi üzerinde yapılmıştır. += operatörü, d_C[ Idx ] adresinin önce okunması, toplam işleminden sonra da tekrar yazılması demektir. Yani d_A ve d_B&#8217;yi saymazsak for döngüsünde toplam 2*n kere hafıza erişimi yapılmaktadır. Halbuki C matrisinin değerini hesaplayıp tek seferde hafızaya yazabiliriz.</div>
<div>matMul2 kernelinde yaratılan değişken ile global GPU RAM erişimi tek thread başına 1 adet yazmaya (d_A ve d_B hariç) düşmüştür.</div>
<pre>
<pre class="brush: cpp; title: ; notranslate">
__global__
void matMul2(
	float* d_C,
	float* d_A,
	float* d_B,
	int m,
	int n,
	int r)
{
	int i = blockIdx.x * BLOCK_SIZE + threadIdx.x;
	int k = blockIdx.y * BLOCK_SIZE + threadIdx.y;

	int cIdx = i*m + k;

	float val = 0; // ara toplam değişkeni

	// C matrisinin her bir hücresi için
	for(int j=0; j&lt;n; j++)
	{
		val += *loc( d_A, n, i, j ) * *loc( d_B, r, j, k );
	}

	// C matrisine bir kere yazılır.
	d_C[ cIdx ] = val;
}
</pre>
</pre>
<h2>Zamanlama</h2>
<p>Yapılan bu ufak değişiklikle kazanılan 128 x 128 boyutlarında iki matrisin çarpım sürelerini karşılaştırabiliriz.<br />
<a href="http://dissipatedHeat.com/wp-content/uploads/2011/04/matmul1-matmul2-timing.png"><img class="aligncenter size-full wp-image-96" title="matMul1 ve matMul2 zamanlaması" src="http://dissipatedHeat.com/wp-content/uploads/2011/04/matmul1-matmul2-timing.png" alt="matMul1 ve matMul2 zamanlaması" width="677" height="342" /></a></p>
<p><strong>Proje dosyasını açabilmek için farklı kaydederek uzantısını <a href="http://www.7-zip.org">7z</a> yapınız.</strong><br />
Kaynakları indir: <a href="http://dissipatedHeat.com/wp-content/uploads/2011/04/CUDA-matris-carpimi-1.txt">CUDA matris carpimi 1</a></p>
<img src="http://feeds.feedburner.com/~r/dheat/~4/kSGaVT1qxbg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://dissipatedHeat.com/2011/04/10/cuda-ile-matris-carpimi-1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://dissipatedHeat.com/2011/04/10/cuda-ile-matris-carpimi-1/</feedburner:origLink></item>
		<item>
		<title>Visual Studio 2010 ile CUDA SDK 3.2 Projesi Yaratmak</title>
		<link>http://feedproxy.google.com/~r/dheat/~3/u2p0u42UjcE/</link>
		<comments>http://dissipatedHeat.com/2011/03/27/visual-studio-2010-ile-cuda-sdk-3-2-projesi-yaratmak/#comments</comments>
		<pubDate>Sun, 27 Mar 2011 15:26:16 +0000</pubDate>
		<dc:creator>Kerem Kat</dc:creator>
				<category><![CDATA[CUDA]]></category>
		<category><![CDATA[Genel]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[nVidia]]></category>
		<category><![CDATA[parallel]]></category>
		<category><![CDATA[visual studio 2010]]></category>
		<category><![CDATA[vs]]></category>
		<category><![CDATA[vs2010]]></category>

		<guid isPermaLink="false">http://dissipatedHeat.com/?p=62</guid>
		<description><![CDATA[CUDA Projelerine Giriş For English: CUDA 3.2 on VS2010 in 9 steps Bu kısa yazımızda CUDA ile programlamaya giriş yapmanın zevkini yaşayacağız. CUDA ile ekran kartındaki GPU üzerinde çalışacak programlar yazabilirsiniz. Bu programlar GPU&#8217;daki özel hardware threadler üzerinde paralel olarak çalışırlar. Detaylı bilgi için tıklayınız. 4. adımdaki dosyalar yok ise indiriniz: CUDA 3.2 Build Rules Aşağıdaki <a href='http://dissipatedHeat.com/2011/03/27/visual-studio-2010-ile-cuda-sdk-3-2-projesi-yaratmak/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<h2>CUDA Projelerine Giriş</h2>
<p>For English: <a href="http://www.codeproject.com/Tips/186655/CUDA-3-2-on-VS2010-in-9-steps">CUDA 3.2 on VS2010 in 9 steps</a></p>
<p>Bu kısa yazımızda CUDA ile programlamaya giriş yapmanın zevkini yaşayacağız. CUDA ile ekran kartındaki GPU üzerinde çalışacak programlar yazabilirsiniz. Bu programlar GPU&#8217;daki özel hardware threadler üzerinde paralel olarak çalışırlar. Detaylı bilgi için <a href="http://www.nvidia.com/object/cuda_home_new.html">tıklayınız</a>.<br />
<span id="more-62"></span><br />
4. adımdaki dosyalar yok ise indiriniz: <a href="http://dissipatedHeat.com/wp-content/uploads/2011/03/CUDA-3.2-Build-Rules.7z">CUDA 3.2 Build Rules</a></p>
<p>Aşağıdaki adımları izlemek için gerekenler:</p>
<ul>
<li>Visual Studio 2008 kurulumu</li>
<li>Visual Studio 2010 kurulumu</li>
<li>nVidia CUDA 3.2 SDK kurulumu</li>
<li>Genel Visual Studio menüleri ve kullanımı</li>
</ul>
<h2>9 Adımda CUDA Derleme</h2>
<ol>
<li>Yeni bir Win32 Console Application yaratın.</li>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/03/1-Create-new-project.png"><img class="size-full wp-image-65" title="Yeni Proje" src="http://dissipatedHeat.com/wp-content/uploads/2011/03/1-Create-new-project.png" alt="" width="955" height="660" /></a></p>
<li>Projeyi yaratırken empty project seçeneğini işaretleyin. Boş bir projeye kaynak dosyasını kendimiz ekleyeceğiz.</li>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/03/2-Select-empty-project.png"><img class="aligncenter size-full wp-image-66" title="Empty Project seçilir" src="http://dissipatedHeat.com/wp-content/uploads/2011/03/2-Select-empty-project.png" alt="" width="615" height="520" /></a></p>
<li>cu uzantılı kaynak dosyası ekleyin. Bu dosya nvidianın compiler driverı olan nvcc.exe dosyası tarafından işlenerek vs2008 ile gelen versiyon 9 C derleyicisine gönderilecektir.</li>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/03/3-add-new-source-file.png"><img class="aligncenter size-full wp-image-67" title="CU kod dosyası eklenir" src="http://dissipatedHeat.com/wp-content/uploads/2011/03/3-add-new-source-file.png" alt="" width="955" height="660" /></a></p>
<li>CUDA 3.2 SDK&#8217;nın <a href="http://developer.nvidia.com/object/cuda_3_2_downloads.html#Windows XP, Windows Vista and Windows7">kuruluşu</a>ile gelen Build Customizationların yerinde olduğu kontrol edilir.</li>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/03/4-add-build-customizations.png"><img class="aligncenter size-full wp-image-68" title="Build Customizations yerinde mi?" src="http://dissipatedHeat.com/wp-content/uploads/2011/03/4-add-build-customizations.png" alt="" width="1010" height="485" /></a></p>
<li>Platform Toolset v90 olarak değiştirilir. Visual Studio 2010, CUDA dosyalarını derlemeyi destekler fakat altyapı olarak bir önceki versiyon C derleyicisini kullanır. Dolayısıyla Visual Studio 2008&#8242;in makinada kurulu olmasına ihtiyaç vardır.</li>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/03/5-change-platform-toolset.png"><img class="aligncenter size-full wp-image-69" title="Derleyici Versiyonu Düşürülür" src="http://dissipatedHeat.com/wp-content/uploads/2011/03/5-change-platform-toolset.png" alt="" width="841" height="594" /></a></p>
<li>Eklediğimiz CU dosyasının özelliklerinden Item Type olarak CUDA C/C++ seçilir.</li>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/03/6-change-.cu-file-property.png"><img class="aligncenter size-full wp-image-70" title="CU Dosyası Item Type değiştirilir" src="http://dissipatedHeat.com/wp-content/uploads/2011/03/6-change-.cu-file-property.png" alt="" width="841" height="594" /></a></p>
<li>Project Build Customizations olarak CUDA 3.2 seçilir. Bende CUDA 3.1 SDK&#8217;sı da yüklü olduğu için o da seçilebiliyor.</li>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/03/7-project-build-customizations.png"><img class="aligncenter size-full wp-image-71" title="Project Build Customizations" src="http://dissipatedHeat.com/wp-content/uploads/2011/03/7-project-build-customizations.png" alt="" width="592" height="348" /></a></p>
<li>CUDA&#8217;nın kullandığı kütüphaneler eklenir( cuda.lib ve cudart.lib ).</li>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/03/8-add-libs.png"><img class="aligncenter size-full wp-image-72" title="cuda.lib ve cudart.lib Kütüphaneler" src="http://dissipatedHeat.com/wp-content/uploads/2011/03/8-add-libs.png" alt="" width="841" height="594" /></a></p>
<li>Yaratılan CU dosyasından CUDA fonksiyonlarının çağrılabildiği ve derlenebildiği görülür.</li>
<p><a href="http://dissipatedHeat.com/wp-content/uploads/2011/03/9-empty-project-succeeded.png"><img class="aligncenter size-full wp-image-73" title="Derlenen CUDA projesi" src="http://dissipatedHeat.com/wp-content/uploads/2011/03/9-empty-project-succeeded.png" alt="" width="1222" height="773" /></a></ol>
<img src="http://feeds.feedburner.com/~r/dheat/~4/u2p0u42UjcE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://dissipatedHeat.com/2011/03/27/visual-studio-2010-ile-cuda-sdk-3-2-projesi-yaratmak/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://dissipatedHeat.com/2011/03/27/visual-studio-2010-ile-cuda-sdk-3-2-projesi-yaratmak/</feedburner:origLink></item>
	</channel>
</rss>

